Script Format Sheet Generator

Script Format Sheet Generator

Script Format Sheet Generator

Standardize and document the formatting rules for your screenplay or teleplay project.

Review the detailed format sheet. Consistency in these rules is crucial for production and readability.

Project:

Format: ${sfsg_escapeHTML(sfsg_data.format)} | Date: ${date}

${formatSheetHTML}
`; } /** * Generates and downloads a PDF of the format sheet */ async function sfsg_downloadPDF() { if (!sfsg_data.title || sfsg_data.elements.length === 0) { alert("Please complete the project title and add at least one element rule before downloading."); return; } if (typeof jspdf === 'undefined' || typeof html2canvas === 'undefined') { alert("Error: PDF libraries failed to load."); return; } sfsg_renderPdfClone(); const { jsPDF } = window.jspdf; try { const contentDiv = sfsg_pdfRenderClone.querySelector('.pdf-content'); if (!contentDiv) return; const canvas = await html2canvas(contentDiv, { scale: 1.5, useCORS: true }); const imgData = canvas.toDataURL('image/png'); const imgProps = { width: canvas.width, height: canvas.height }; const pdf = new jsPDF({ orientation: 'p', unit: 'pt', format: 'a4' }); const pdfWidth = pdf.internal.pageSize.getWidth(); const pdfHeight = pdf.internal.pageSize.getHeight(); const margin = 40; const contentWidth = pdfWidth - (margin * 2); const contentHeight = (contentWidth * imgProps.height) / imgProps.width; let heightLeft = contentHeight; let position = 0; pdf.addImage(imgData, 'PNG', margin, position + margin, contentWidth, contentHeight); heightLeft -= (pdfHeight - margin * 2); while (heightLeft > 0) { position -= (pdfHeight - margin * 2); pdf.addPage(); pdf.addImage(imgData, 'PNG', margin, position + margin, contentWidth, contentHeight); heightLeft -= (pdfHeight - margin * 2); } const safeName = (sfsg_data.title || 'format_sheet').replace(/[^a-z0-9]/gi, '_').toLowerCase(); pdf.save(`${safeName}_Format_Sheet.pdf`); } catch (error) { console.error("PDF generation failed:", error); alert("An error occurred while generating the PDF."); } } // --- EVENT LISTENERS --- // Tab link clicks sfsg_tabLinks.forEach((link, index) => { link.addEventListener('click', () => sfsg_switchTab(index)); }); // Next/Prev button clicks if (sfsg_prevButton) { sfsg_prevButton.addEventListener('click', () => { if (sfsg_currentTab > 0) sfsg_switchTab(sfsg_currentTab - 1); }); } if (sfsg_nextButton) { sfsg_nextButton.addEventListener('click', () => { if (sfsg_currentTab === sfsg_tabLinks.length - 1) { sfsg_updateDataFromConfig(); sfsg_switchTab(0); } else { if (sfsg_currentTab < sfsg_tabLinks.length - 1) sfsg_switchTab(sfsg_currentTab + 1); } }); } // PDF download if (sfsg_downloadPdfButton) { sfsg_downloadPdfButton.addEventListener('click', sfsg_downloadPDF); } // --- Config Tab Listeners --- if (sfsg_addElementButton) { sfsg_addElementButton.addEventListener('click', () => { sfsg_elementsContainer.appendChild(sfsg_createElementInput()); }); } if (sfsg_configTab) { // Handle removal sfsg_configTab.addEventListener('click', (e) => { const removeButton = e.target.closest('.sfsg-remove-item'); if (removeButton) { removeButton.closest('.p-3[data-id]').remove(); } }); } // --- INITIALIZATION --- sfsg_renderConfig(); sfsg_renderDashboard(); // Set initial tab state sfsg_tabPanes.forEach((pane, index) => { pane.classList.toggle('hidden', index !== 0); pane.classList.toggle('sfsg-active', index === 0); }); sfsg_tabLinks.forEach((link, index) => { TAB_CLASSES.active.forEach(cls => link.classList.remove(cls)); TAB_CLASSES.inactive.forEach(cls => link.classList.remove(cls)); if (index === 0) { TAB_CLASSES.active.forEach(cls => link.classList.add(cls)); } else { TAB_CLASSES.inactive.forEach(cls => link.classList.add(cls)); } }); });
Scroll to Top