Fanfiction Outline Generator

Fanfiction Outline Generator

1. Story Metadata
2. Plot Structure

Add New Plot Structure

Add New Structure

Available Plot Structures

Name Key Points (Preview) Actions

Fill out the Builder tab and click "Generate Outline Draft" to preview your story structure.

Genre: ${data.metadata.genre || 'N/A'}

Premise: ${data.metadata.summary || 'No summary provided.'}

${data.structure} Outline

`; // --- Plot Points --- data.plotPoints.forEach((point, index) => { html += `

${index + 1}. ${point.label}

${point.content || '(Plot point details missing)'}

`; }); reviewContent.innerHTML = html; pdfDownloadBtn.disabled = false; switchTab(2); // Switch to review tab }; /** * PDF Generation Function (Fully Functional) */ const downloadPDF = () => { const data = getOutlineData(); const jsPDF = window.jspdf.jsPDF; const doc = new jsPDF('p', 'pt', 'a4'); let currentY = 40; const margin = 40; const pageWidth = doc.internal.pageSize.width; const maxWidth = pageWidth - (margin * 2); const checkPageBreak = (spaceNeeded) => { if (currentY + spaceNeeded > doc.internal.pageSize.height - margin) { doc.addPage(); currentY = margin; } }; const addText = (text, size = 10, style = 'normal', indent = 0) => { doc.setFontSize(size); doc.setFont('Helvetica', style); const lines = doc.splitTextToSize(text, maxWidth - indent); checkPageBreak(lines.length * (size * 1.2)); doc.text(lines, margin + indent, currentY); currentY += (lines.length * (size * 1.2)); }; // --- PDF Content --- // Title Block doc.setFontSize(22); doc.setFont('Helvetica', 'bold'); doc.setTextColor(106, 90, 205); doc.text(data.metadata.title.toUpperCase() || 'UNTITLED FANFICTION', pageWidth / 2, currentY, { align: 'center' }); currentY += 15; doc.setFontSize(12); doc.setTextColor(74, 78, 105); addText(`Fandom: ${data.metadata.fandom || 'N/A'} | Pairing/MC: ${data.metadata.pairing || 'N/A'} | Genre: ${data.metadata.genre || 'N/A'}`, 12, 'normal', 0); currentY += 5; doc.setFontSize(10); addText(`Premise: ${data.metadata.summary || 'No summary provided.'}`, 10, 'italic', 0); currentY += 20; // Outline Header doc.setFontSize(16); doc.setFont('Helvetica', 'bold'); doc.setTextColor(106, 90, 205); doc.text(`${data.structure} Outline`, margin, currentY); currentY += 5; doc.setLineWidth(0.5); doc.setDrawColor(200); doc.line(margin, currentY, pageWidth - margin, currentY); currentY += 15; doc.setTextColor(0); // Plot Points data.plotPoints.forEach((point, index) => { checkPageBreak(30); // Point Label (Header) doc.setFontSize(12); doc.setFont('Helvetica', 'bold'); doc.setTextColor(74, 78, 105); addText(`${index + 1}. ${point.label}`, 12, 'bold', 0); // Point Content doc.setFontSize(11); doc.setFont('Helvetica', 'normal'); addText(point.content || '(Plot point details missing)', 11, 'normal', 10); currentY += 5; }); doc.save(`${data.metadata.title.replace(/\s/g, '_') || 'Fanfiction'}_Outline.pdf`); }; // --- Event Listeners and Initial Load --- plotStructureSelect.addEventListener('change', loadStructure); generateOutlineBtn.addEventListener('click', generateOutline); pdfDownloadBtn.addEventListener('click', downloadPDF); // Tab Navigation const switchTab = (tabIndex) => { tabs.forEach((tab, index) => { tab.classList.toggle('active', index === tabIndex); contents[index].classList.toggle('active', index === tabIndex); }); currentTab = tabIndex; updateNavButtons(); if (tabIndex === 2) { generateOutline(); } else if (tabIndex === 1) { renderStructureList(); } }; const updateNavButtons = () => { prevBtn.disabled = currentTab === 0; nextBtn.disabled = currentTab === tabs.length - 1; }; tabs.forEach((tab, index) => { tab.addEventListener('click', () => { const tabNode = tab.closest('.ff-tab-button'); const newIndex = Array.from(tabNode.parentNode.children).indexOf(tabNode); switchTab(newIndex); }); }); nextBtn.addEventListener('click', () => { if (currentTab < tabs.length - 1) switchTab(currentTab + 1); }); prevBtn.addEventListener('click', () => { if (currentTab > 0) switchTab(currentTab - 1); }); // Initial Setup renderStructureList(); updateNavButtons(); });
Scroll to Top