// Global variables let quill; let currentMode = 'richtext'; let currentContent = ''; let pages = []; // Initialize Quill editor function initQuill() { quill = new Quill('#quillEditor', { theme: 'snow', modules: { toolbar: '#quillToolbar' }, placeholder: 'Start writing your letter content here...' }); // Update preview on content change quill.on('text-change', () => { updatePreview(); }); } // Mode switching document.getElementById('richTextMode').addEventListener('click', () => { switchMode('richtext'); }); document.getElementById('markdownMode').addEventListener('click', () => { switchMode('markdown'); }); document.getElementById('previewMode').addEventListener('click', () => { switchMode('preview'); }); function switchMode(mode) { // Update button states document.querySelectorAll('.toolbar-left .btn').forEach(btn => { btn.classList.remove('active', 'btn-primary'); }); // Hide all editors document.querySelectorAll('.editor-mode').forEach(editor => { editor.classList.remove('active'); }); currentMode = mode; switch(mode) { case 'richtext': document.getElementById('richTextMode').classList.add('active', 'btn-primary'); document.getElementById('richTextEditor').classList.add('active'); // Convert markdown to rich text if switching from markdown if (currentMode === 'markdown') { const markdownContent = document.getElementById('markdownTextarea').value; const html = marked.parse(markdownContent); quill.root.innerHTML = DOMPurify.sanitize(html); } break; case 'markdown': document.getElementById('markdownMode').classList.add('active', 'btn-primary'); document.getElementById('markdownEditor').classList.add('active'); // Convert rich text to markdown if switching from rich text if (currentMode === 'richtext') { const html = quill.root.innerHTML; document.getElementById('markdownTextarea').value = htmlToMarkdown(html); } break; case 'preview': document.getElementById('previewMode').classList.add('active', 'btn-primary'); // Hide editor section document.querySelector('.editor-section').style.display = 'none'; document.querySelector('.preview-section').style.flex = '1'; break; } if (mode !== 'preview') { document.querySelector('.editor-section').style.display = 'flex'; document.querySelector('.preview-section').style.flex = '1'; } updatePreview(); } // Markdown editor functions function insertMarkdown(before, after) { const textarea = document.getElementById('markdownTextarea'); const start = textarea.selectionStart; const end = textarea.selectionEnd; const selectedText = textarea.value.substring(start, end); const replacement = before + selectedText + after; textarea.value = textarea.value.substring(0, start) + replacement + textarea.value.substring(end); textarea.focus(); textarea.setSelectionRange(start + before.length, start + before.length + selectedText.length); updatePreview(); } function insertTable() { const table = '\n| Header 1 | Header 2 | Header 3 |\n|----------|----------|----------|\n| Cell 1 | Cell 2 | Cell 3 |\n| Cell 4 | Cell 5 | Cell 6 |\n'; const textarea = document.getElementById('markdownTextarea'); const start = textarea.selectionStart; textarea.value = textarea.value.substring(0, start) + table + textarea.value.substring(start); textarea.focus(); textarea.setSelectionRange(start + table.length, start + table.length); updatePreview(); } // Update preview on markdown change document.getElementById('markdownTextarea').addEventListener('input', updatePreview); // Convert HTML to Markdown (basic conversion) function htmlToMarkdown(html) { let markdown = html; // Headers markdown = markdown.replace(/
]*>(.*?)<\/p>/gi, '$1\n\n');
// Line breaks
markdown = markdown.replace(/
]*>/gi, '\n');
// Remove remaining HTML tags
markdown = markdown.replace(/<[^>]*>/g, '');
// Clean up extra whitespace
markdown = markdown.replace(/\n\n+/g, '\n\n').trim();
return markdown;
}
// Update preview function
function updatePreview() {
let content = '';
if (currentMode === 'richtext') {
content = quill.root.innerHTML;
} else if (currentMode === 'markdown') {
const markdownContent = document.getElementById('markdownTextarea').value;
content = marked.parse(markdownContent);
}
currentContent = DOMPurify.sanitize(content);
paginateContent();
}
// Paginate content
function paginateContent() {
const container = document.getElementById('previewContainer');
container.innerHTML = '';
// Create a temporary element to measure content
const tempDiv = document.createElement('div');
tempDiv.style.cssText = 'position: absolute; visibility: hidden; width: 130mm; font-size: 16px; line-height: 1.6;';
tempDiv.innerHTML = currentContent;
document.body.appendChild(tempDiv);
// Split content into pages
const maxHeight = 200; // mm - approximate content area height
const elements = Array.from(tempDiv.children);
pages = [];
let currentPage = [];
let currentHeight = 0;
elements.forEach(element => {
const elementHeight = element.offsetHeight / 3.78; // Convert px to mm (approximate)
if (currentHeight + elementHeight > maxHeight && currentPage.length > 0) {
pages.push(currentPage);
currentPage = [];
currentHeight = 0;
}
currentPage.push(element.outerHTML);
currentHeight += elementHeight;
});
if (currentPage.length > 0) {
pages.push(currentPage);
}
// If no pages created, create one with all content
if (pages.length === 0) {
pages.push([currentContent]);
}
document.body.removeChild(tempDiv);
// Create preview pages
pages.forEach((pageContent, index) => {
const pageDiv = createPreviewPage(pageContent.join(''), index + 1);
container.appendChild(pageDiv);
});
// Update page info
document.getElementById('currentPage').textContent = '1';
document.getElementById('totalPages').textContent = pages.length;
}
// Create preview page
function createPreviewPage(content, pageNumber) {
const pageDiv = document.createElement('div');
pageDiv.className = 'preview-page';
pageDiv.innerHTML = `