// GhostEditor - Markdown to Word Converter JavaScript document.addEventListener('DOMContentLoaded', function() { // DOM Elements const markdownInput = document.getElementById('markdownInput'); const previewOutput = document.getElementById('previewOutput'); const previewToggle = document.getElementById('previewToggle'); const exportBtn = document.getElementById('exportBtn'); const blockType = document.getElementById('blockType'); const applyStyle = document.getElementById('applyStyle'); const applyStyleBtn = document.getElementById('applyStyleBtn'); const customCaption = document.getElementById('customCaption'); const applyCaptionBtn = document.getElementById('applyCaptionBtn'); const autoCaptionImages = document.getElementById('autoCaptionImages'); const autoCaptionTables = document.getElementById('autoCaptionTables'); const autoCaptionFigures = document.getElementById('autoCaptionFigures'); const tablePagination = document.getElementById('tablePagination'); const boldBtn = document.getElementById('boldBtn'); const italicBtn = document.getElementById('italicBtn'); const headingBtn = document.getElementById('headingBtn'); const listBtn = document.getElementById('listBtn'); const imageBtn = document.getElementById('imageBtn'); // Configuration let config = { autoCaptionImages: true, autoCaptionTables: true, autoCaptionFigures: true, tablePagination: true, defaultStyle: 'Normal' }; // Initialize with sample markdown markdownInput.value = `# GhostEditor Sample Document This is a sample document to demonstrate the real-time conversion capabilities of GhostEditor. ## Features Demonstrated ### Auto-captioning ![Sample Image](https://via.placeholder.com/150) *Figure 1: Sample placeholder image* ### Table with Pagination Support | ID | Name | Role | |----|------|------| | 1 | John | Developer | | 2 | Jane | Designer | | 3 | Bob | Manager | | 4 | Alice | Analyst | ### Code Block \`\`\`python def hello_world(): print("Hello, GhostEditor!") \`\`\` ### Blockquote > This is a sample quote demonstrating the styling capabilities of GhostEditor. ### List - First item - Second item - Third item`; // Update configuration when settings change autoCaptionImages.addEventListener('change', updateConfig); autoCaptionTables.addEventListener('change', updateConfig); autoCaptionFigures.addEventListener('change', updateConfig); tablePagination.addEventListener('change', updateConfig); // Toolbar buttons boldBtn.addEventListener('click', () => wrapText('**', '**')); italicBtn.addEventListener('click', () => wrapText('*', '*')); headingBtn.addEventListener('click', () => wrapLine('# ')); listBtn.addEventListener('click', () => wrapLine('- ')); imageBtn.addEventListener('click', () => insertImage()); // Apply style button applyStyleBtn.addEventListener('click', applyStyleToSelection); // Apply caption button applyCaptionBtn.addEventListener('click', applyCaptionToSelection); // Export button exportBtn.addEventListener('click', exportToWord); // Initial preview update updatePreview(); // Update preview when input changes markdownInput.addEventListener('input', updatePreview); // Update preview when toggle changes previewToggle.addEventListener('change', function() { if (this.checked) { updatePreview(); } else { previewOutput.innerHTML = '

Preview is disabled. Enable to see real-time conversion.

'; } }); // Update configuration function updateConfig() { config = { autoCaptionImages: autoCaptionImages.checked, autoCaptionTables: autoCaptionTables.checked, autoCaptionFigures: autoCaptionFigures.checked, tablePagination: tablePagination.checked, defaultStyle: document.getElementById('defaultStyle').value }; // Update preview after config change updatePreview(); } // Update preview function function updatePreview() { if (!previewToggle.checked) return; const markdown = markdownInput.value; // Convert markdown to HTML using Marked.js const html = marked.parse(markdown); // Process the HTML to add captions and table pagination const processedHtml = processHtmlForPreview(html); previewOutput.innerHTML = processedHtml; // Add captions to images if enabled if (config.autoCaptionImages) { addImageCaptions(); } } // Process HTML for preview with special features function processHtmlForPreview(html) { let processed = html; // Add table pagination header if enabled if (config.tablePagination) { processed = processed.replace(//g, '
'); } return processed; } // Add captions to images function addImageCaptions() { const images = previewOutput.querySelectorAll('img'); images.forEach((img, index) => { // Check if image already has a caption if (!img.nextElementSibling || !img.nextElementSibling.classList.contains('caption')) { const caption = document.createElement('div'); caption.className = 'caption'; caption.textContent = `Figure ${index + 1}: ${img.alt || 'Image'}`; img.parentNode.insertBefore(caption, img.nextSibling); } }); } // Apply style to selected text function applyStyleToSelection() { const selectedStyle = applyStyle.value; const selectedBlock = blockType.value; // In a real implementation, this would modify the markdown // For now, we'll just show a preview of the style showStylePreview(selectedStyle); } // Show style preview function showStylePreview(style) { const previewDiv = document.getElementById('stylePreview'); let styleExample = ''; switch(style) { case 'Heading1': styleExample = '

Heading 1 Example

'; break; case 'Heading2': styleExample = '

Heading 2 Example

'; break; case 'Heading3': styleExample = '

Heading 3 Example

'; break; case 'Quote': styleExample = '
This is a quote example
'; break; case 'Code': styleExample = 'This is a code example'; break; default: styleExample = '

This is a normal paragraph example

'; } previewDiv.innerHTML = styleExample; } // Apply caption to selection function applyCaptionToSelection() { const captionText = customCaption.value.trim(); if (!captionText) return; // In a real implementation, this would add the caption to the markdown // For now, we'll just show a notification alert(`Caption applied: ${captionText}`); } // Wrap selected text with markdown syntax function wrapText(before, after) { const start = markdownInput.selectionStart; const end = markdownInput.selectionEnd; const selectedText = markdownInput.value.substring(start, end); const newText = before + selectedText + after; markdownInput.value = markdownInput.value.substring(0, start) + newText + markdownInput.value.substring(end); // Update cursor position markdownInput.selectionStart = start + before.length; markdownInput.selectionEnd = start + before.length + selectedText.length; updatePreview(); } // Wrap current line with markdown syntax function wrapLine(prefix) { const start = markdownInput.selectionStart; const end = markdownInput.selectionEnd; const text = markdownInput.value; // Find start and end of current line const lineStart = text.lastIndexOf('\n', start - 1) + 1; const lineEnd = text.indexOf('\n', end); const actualLineEnd = lineEnd === -1 ? text.length : lineEnd; const lineText = text.substring(lineStart, actualLineEnd); const newLineText = prefix + lineText; markdownInput.value = text.substring(0, lineStart) + newLineText + text.substring(actualLineEnd); // Update cursor position markdownInput.selectionStart = start + prefix.length; markdownInput.selectionEnd = end + prefix.length; updatePreview(); } // Insert image markdown function insertImage() { const start = markdownInput.selectionStart; const end = markdownInput.selectionEnd; const selectedText = markdownInput.value.substring(start, end); const altText = selectedText || 'image'; const imageMd = `![${altText}](path/to/image.png)`; markdownInput.value = markdownInput.value.substring(0, start) + imageMd + markdownInput.value.substring(end); // Update cursor position markdownInput.selectionStart = start + 2; // Position cursor in the alt text markdownInput.selectionEnd = start + 2 + altText.length; updatePreview(); } // Export to Word functionality function exportToWord() { // In a real implementation, this would send the markdown to the backend // to convert it to Word format alert('Exporting to Word document...'); // Create a form to submit the markdown to the backend const form = document.createElement('form'); form.method = 'POST'; form.action = '/export'; form.style.display = 'none'; const markdownField = document.createElement('input'); markdownField.type = 'hidden'; markdownField.name = 'markdown'; markdownField.value = markdownInput.value; const configField = document.createElement('input'); configField.type = 'hidden'; configField.name = 'config'; configField.value = JSON.stringify(config); form.appendChild(markdownField); form.appendChild(configField); document.body.appendChild(form); form.submit(); document.body.removeChild(form); } // Initialize style preview showStylePreview(config.defaultStyle); });