research / templates /index.html
mfoud444's picture
Update templates/index.html
4443837 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Markdown to DOCX Converter</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/highlight.js@11.7.0/lib/core.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/highlight.js@11.7.0/styles/github.min.css">
<style>
.editor-container {
height: calc(100vh - 200px);
}
#markdown-input, #markdown-preview {
height: 100%;
overflow-y: auto;
}
#markdown-preview {
border-left: 1px solid #e2e8f0;
}
.hljs {
background: #f8fafc;
border-radius: 0.25rem;
padding: 1rem;
}
.hljs pre {
margin: 0;
}
</style>
</head>
<body class="bg-gray-50">
<div class="container mx-auto px-4 py-8">
<header class="mb-8 text-center">
<h1 class="text-3xl font-bold text-gray-800 mb-2">Markdown to DOCX Converter</h1>
<p class="text-gray-600">Write your Markdown and convert it to a professional DOCX document</p>
</header>
<div class="bg-white rounded-lg shadow-md overflow-hidden mb-6">
<div class="flex justify-between items-center bg-gray-100 px-4 py-3 border-b border-gray-200">
<h2 class="font-semibold text-gray-700">Editor</h2>
<div class="flex space-x-2">
<button id="preview-toggle" class="px-3 py-1 bg-gray-200 text-gray-700 rounded-md text-sm hover:bg-gray-300 md:hidden">
Toggle Preview
</button>
<button id="convert-btn" class="px-3 py-1 bg-blue-600 text-white rounded-md text-sm hover:bg-blue-700 flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-1" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12" />
</svg>
Convert to DOCX
</button>
</div>
</div>
<div class="flex flex-col md:flex-row editor-container">
<div class="w-full md:w-1/2 p-4">
<textarea id="markdown-input" class="w-full h-full p-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-blue-500 focus:border-blue-500 resize-none" placeholder="# Start writing your Markdown here...
## Headers
Use # for h1, ## for h2 etc.
## Lists
- Item 1
- Item 2
## Code
```javascript
console.log('Hello World');
```
## More formatting
**Bold**, *italic*, [links](https://example.com)"></textarea>
</div>
<div id="markdown-preview" class="w-full md:w-1/2 p-4 prose max-w-none"></div>
</div>
</div>
<div id="status-message" class="hidden fixed bottom-4 right-4 bg-blue-100 border border-blue-400 text-blue-700 px-4 py-3 rounded"></div>
</div>
<script>
// Initialize Marked with Highlight.js for code highlighting
marked.setOptions({
highlight: function(code, lang) {
const language = hljs.getLanguage(lang) ? lang : 'plaintext';
return hljs.highlight(code, { language }).value;
},
langPrefix: 'hljs language-',
breaks: true,
gfm: true
});
// Elements
const markdownInput = document.getElementById('markdown-input');
const markdownPreview = document.getElementById('markdown-preview');
const convertBtn = document.getElementById('convert-btn');
const previewToggle = document.getElementById('preview-toggle');
const statusMessage = document.getElementById('status-message');
// Update preview on input
function updatePreview() {
markdownPreview.innerHTML = marked.parse(markdownInput.value);
}
// Initial preview update
updatePreview();
// Event listeners
markdownInput.addEventListener('input', updatePreview);
previewToggle.addEventListener('click', () => {
markdownPreview.classList.toggle('hidden');
markdownInput.classList.toggle('w-full');
});
convertBtn.addEventListener('click', async () => {
const markdown = markdownInput.value.trim();
if (!markdown) {
showStatus('Please enter some Markdown content', 'error');
return;
}
try {
convertBtn.disabled = true;
convertBtn.innerHTML = `
<svg class="animate-spin -ml-1 mr-2 h-4 w-4 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
Converting...
`;
showStatus('Converting to DOCX...', 'info');
// First send the markdown to the conversion endpoint
const response = await fetch('/api/convert', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
markdown: markdown
})
});
if (!response.ok) {
throw new Error(`Server returned ${response.status}`);
}
const result = await response.json();
if (!result.success) {
throw new Error(result.message || 'Conversion failed');
}
// Then download the generated file
const downloadResponse = await fetch(`/api/download/${result.filename}`);
if (!downloadResponse.ok) {
throw new Error('Failed to download file');
}
const blob = await downloadResponse.blob();
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = result.filename || 'document.docx';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
showStatus('Document downloaded successfully!', 'success');
} catch (error) {
console.error('Conversion error:', error);
showStatus('Error converting document: ' + error.message, 'error');
} finally {
convertBtn.disabled = false;
convertBtn.innerHTML = `
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-1" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12" />
</svg>
Convert to DOCX
`;
}
});
function showStatus(message, type) {
statusMessage.textContent = message;
statusMessage.className = `fixed bottom-4 right-4 px-4 py-3 rounded`;
if (type === 'error') {
statusMessage.classList.add('bg-red-100', 'border-red-400', 'text-red-700');
} else if (type === 'success') {
statusMessage.classList.add('bg-green-100', 'border-green-400', 'text-green-700');
} else {
statusMessage.classList.add('bg-blue-100', 'border-blue-400', 'text-blue-700');
}
statusMessage.classList.remove('hidden');
setTimeout(() => {
statusMessage.classList.add('hidden');
}, 5000);
}
</script>
</body>
</html>