PageSourceSearch

https://formatmagic.ai/static/dist/scripts.Bakmt0kZ.js

js formatmagic.ai collected 2026-10-05 11:59:24 UTC 60,636 bytes, 1 lines download raw bytes

1import{i as e,e as t,r as n,u as o,s}from"./chunks/long-run-notify-CqomOApd.js";function a(e){const t=document.getElementById("userInput"),n=t.selectionStart,o=t.selectionEnd,s=t.value.substring(n,o);let a="";const r=t.scrollTop;function i(e,t){return{bold:/^\*\*.*\*\*$/,italic:/^\*.*\*$/,heading:/^#+\s/,link:/^\[.*\]\(.*\)$/}[t].test(e.trim())}switch(e){case"bold":a=i(s,"bold")?s.slice(2,-2):`**${s}**`;break;case"italic":a=i(s,"italic")?s.slice(1,-1):`*${s}*`;break;case"heading1":case"heading2":case"heading3":case"heading4":case"heading5":const n=e.charAt(e.length-1);a=i(s,"heading")?s.replace(/^#+\s/,`${"#".repeat(parseInt(n))} `):`${"#".repeat(parseInt(n))} ${s}`;break;case"link":if(i(s,"link"))return;let o=prompt("Enter the URL:");if(!o)return;/^https?:\/\//i.test(o)||(o="https://"+o),a=`[${s}](${o})`;break;case"pagebreak":a="!!!*!!! page break";break;case"cut":if(t.selectionStart!==t.selectionEnd){const e=t.value.substring(t.selectionStart,t.selectionEnd);navigator.clipboard.writeText(e).then(()=>{const e=t.selectionStart;t.value=t.value.slice(0,t.selectionStart)+t.value.slice(t.selectionEnd),t.selectionStart=t.selectionEnd=e})}return;case"copy":if(t.selectionStart!==t.selectionEnd){const e=t.value.substring(t.selectionStart,t.selectionEnd);navigator.clipboard.writeText(e)}return;case"paste":return void navigator.clipboard.readText().then(e=>{const n=t.selectionStart;t.value=t.value.slice(0,t.selectionStart)+e+t.value.slice(t.selectionEnd),t.selectionStart=t.selectionEnd=n+e.length})}t.value="pagebreak"===e?t.value.substring(0,n)+a+t.value.substring(n):"toc"===e?a+t.value:t.value.substring(0,n)+a+t.value.substring(o),t.scrollTop=r,"pagebreak"===e?t.setSelectionRange(n+a.length,n+a.length):"toc"===e?t.setSelectionRange(a.length,a.length):t.setSelectionRange(n,n+a.length)}async function r(){try{const e=await fetch("/api/subscription_tiers"),t=await e.json();t.sort((e,t)=>0===e.price||"free"===e.name.toLowerCase()?-1:0===t.price||"free"===t.name.toLowerCase()||null===e.price||void 0===e.price?1:null===t.price||void 0===t.price?-1:e.price-t.price);const n=document.getElementById("subscription-options");n?t.forEach(e=>{const t=`tier-template-${e.name.toLowerCase()}`,o=document.getElementById(t);if(o){let t=o.innerHTML;t=t.replace(/{name}/g,e.name).replace(/{price}/g,function(e){if(null==e)return"Custom pricing";return e.toString()}(e.price)).replace(/{tokens}/g,i(e.tokens)).replace(/{max_tokens_per_request}/g,i(e.max_tokens_per_request)).replace(/{id}/g,e.id);const s=document.createElement("div");s.innerHTML=t;s.querySelector(".subscribe-button").addEventListener("click",()=>async function(e){try{const t=await fetch(`/api/subscribe/${e}`,{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include"});if(401===t.status)return void(window.location.href=`/register?plan=${e}`);if(!t.ok)throw new Error("Subscription failed");const n=await t.json();if(n.sessionId){Stripe("pk_live_51PzZ0rRpsjN8HX5bqX02tWr35CiPtXb78kbcRSAHMhU4bKrABQC89LQRAumdSebkxBrBzGjt6F7PF2NI3RZG5SGW00G1b6oBD2").redirectToCheckout({sessionId:n.sessionId})}else n.redirect?window.location.href=n.redirect:(document.getElementById("subscription-message").textContent=n.message,document.getElementById("error-message").textContent="")}catch(e){console.error("Error:",e),document.getElementById("error-message").textContent="An error occurred. Please try again.",document.getElementById("subscription-message").textContent=""}}(e.id)),n.appendChild(s.firstElementChild)}else console.log(`Template not found for tier: ${e.name}`)}):console.log("Subscription options container not found")}catch(e){console.error("Error fetching subscription tiers:",e)}}function i(e){return null==e?"Custom":e.toLocaleString()}const l=["custom","basictemplate","business","resume","coverletter"],c={custom:"/static/sample_business.txt",business:"/static/sample_business.txt",resume:"/static/sample_resume.txt",coverletter:"/static/sample_coverletter.txt",basictemplate:"/static/sample_business.txt","my-custom-templates":"/static/sample_business.txt"};let d="custom",u=null;async function m(){return window.__templatesPromise||(window.__templatesPromise=(async()=>{try{const e=new AbortController,t=setTimeout(()=>e.abort(),1e4),n=await fetch("/api/templates",{signal:e.signal});if(clearTimeout(t),!n.ok)throw new Error(`HTTP error! status: ${n.status}`);return await n.json()}catch(e){if(window.__templatesPromise=null,console.error("Error fetching templates:",e),"AbortError"===e.name)throw new Error("Request timed out after 10 seconds");throw e}})()),window.__templatesPromise}async function p(){console.log("🔄 Fetching user custom templates...");try{const e=new AbortController,t=setTimeout(()=>e.abort(),1e4),n=await fetch("/api/custom-templates/",{signal:e.signal});if(clearTimeout(t),!n.ok){if(401===n.status)throw new Error("Please log in to view your custom templates");throw new Error(`HTTP error! status: ${n.status}`)}const o=await n.json();return console.log(`✅ Fetched ${o.length} custom templates`),o}catch(e){if(console.error("❌ Error fetching user custom templates:",e),"AbortError"===e.name)throw new Error("Request timed out after 10 seconds");throw e}}async function g(e){d=e;const t=document.querySelector(".image-gallery");t&&(t.innerHTML='<div class="spinner-border text-primary" role="status"><span class="visually-hidden">Loading...</span></div>');const n=document.getElementById("basicTemplatesInfoContainer");n&&(n.style.display="basictemplate"===e?"":"none");const o=!(!window.__wordMode||!window.__wordMode.active),s=document.getElementById("customTemplatesInfoContainer");s&&(s.style.display="my-custom-templates"!==e||o?"none":"");try{let t;
1if("my-custom-templates"===e){t=(await p()).map(e=>({id:e.template_id,category:e.category,title:e.name,description:e.description,image_url:e.image_url,alt_text:e.name,source:"user-custom"}))}else{t=(await m()).filter(t=>t.category===e&&"custom"!==t.source)}!function(e,t=!1){const n=document.querySelector(".image-gallery");if(!n)return;if(n.innerHTML="",!e||0===e.length)return void(n.innerHTML=t?'\n                <div class="custom-templates-empty-state text-center p-4">\n                    <i class="bi bi-palette" style="font-size: 3rem; color: #6c757d;"></i>\n                    <h5 class="mt-3">No Custom Templates Yet</h5>\n                    <p class="text-muted">Create your first custom template with your own colors, fonts, and styling.</p>\n                    <a href="/customize-template" class="btn btn-primary mt-2">\n                        <i class="bi bi-plus-circle me-2"></i>Create Custom Template\n                    </a>\n                </div>\n            ':"<p>No templates available for this category.</p>");e.forEach((e,o)=>{const s="basictemplate"===e.category&&window.userSubscription&&!window.userSubscription.isPaying,a="user-custom"===e.source||t,r=document.createElement("div");r.className="template-container",s&&r.classList.add("template-locked"),a&&r.classList.add("user-custom-template"),r.dataset.templateId=e.id,r.dataset.category=e.category;const i=document.createElement("img");i.alt=e.alt_text||e.title,i.className="gallery-image img-fluid",i.dataset.templateId=e.id,i.dataset.templateTitle=e.title,i.src=e.image_url,i.loading="lazy",i.addEventListener("load",f,{once:!0});const l=document.createElement("div");if(l.className="template-name-label",l.textContent=e.title,r.appendChild(l),s){const e=document.createElement("div");e.className="template-lock-overlay",e.innerHTML='\n                <div class="lock-icon">\n                    <i class="bi bi-lock-fill"></i>\n                </div>\n                <div class="premium-badge">Premium</div>\n            ',r.appendChild(e)}const c=window.userSubscription&&window.userSubscription.hasCustomTemplateAccess;if((a||["business","coverletter","basictemplate","resume"].includes(e.category))&&c){const t=document.createElement("div");t.className="template-edit-overlay",t.innerHTML=a?`\n                    <a href="/customize-template?template_id=${e.id}" class="edit-template-btn" title="Edit Template">\n                        <i class="bi bi-pencil-fill"></i>\n                    </a>\n                    <button class="delete-template-btn" data-template-id="${e.id}" data-template-name="${e.title}" title="Delete Template">\n                        <i class="bi bi-trash-fill"></i>\n                    </button>\n                `:`\n                    <a href="/customize-template?base=${e.id}" class="edit-template-btn customize-base-btn" title="Customize Template">\n                        <i class="bi bi-pencil-fill"></i>\n                    </a>\n                `,r.appendChild(t)}r.appendChild(i),r.addEventListener("click",t=>{t.target.closest(".edit-template-btn")||t.target.closest(".delete-template-btn")||h(e)});const d=r.querySelector(".delete-template-btn");d&&d.addEventListener("click",t=>{t.preventDefault(),t.stopPropagation(),function(e,t){const n=document.getElementById("appModal"),o=document.getElementById("appModalLabel"),s=document.getElementById("appModalBody"),a=document.getElementById("appModalFooter");if(!n)return void console.error("Modal element not found");o.textContent="Delete Custom Template",s.innerHTML=`\n        <div class="text-center">\n            <div class="mb-3">\n                <i class="bi bi-exclamation-triangle-fill" style="font-size: 48px; color: #dc3545;"></i>\n            </div>\n            <h5 class="mb-3">Are you sure?</h5>\n            <p class="mb-0">\n                You are about to delete "<strong>${t}</strong>".\n            </p>\n            <p class="text-muted">\n                This action cannot be undone.\n            </p>\n        </div>\n    `,a.innerHTML='\n        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>\n        <button type="button" class="btn btn-danger" id="confirmDeleteBtn">\n            <i class="bi bi-trash-fill me-2"></i>Delete Template\n        </button>\n    ',a.style.display="flex";const r=new bootstrap.Modal(n);r.show();const i=document.getElementById("confirmDeleteBtn");i.addEventListener("click",async()=>{i.disabled=!0,i.innerHTML='<span class="spinner-border spinner-border-sm me-2"></span>Deleting...';try{await async function(e){console.log(`🗑️ Deleting custom template: ${e}`);const t=document.querySelector('meta[name="csrf-token"]')?.getAttribute("content"),n={"Content-Type":"application/json"};t&&(n["X-CSRF-Token"]=t);const o=await fetch(`/api/custom-templates/${e}`,{method:"DELETE",headers:n});if(!o.ok){const e=await o.json().catch(()=>({}));throw new Error(e.detail||`HTTP error! status: ${o.status}`)}return console.log(`✅ Template ${e} deleted successfully`),await o.json()}(e),s.innerHTML='\n                <div class="text-center">\n                    <i class="bi bi-check-circle-fill text-success" style="font-size: 48px;"></i>\n                    <p class="mt-3 mb-0">Template deleted successfully!</p>\n                </div>\n            ',a.style.display="none",setTimeout(()=>{r.hide(),g("my-custom-templates")}
1,1e3)}catch(e){s.innerHTML=`\n                <div class="text-center">\n                    <i class="bi bi-x-circle-fill text-danger" style="font-size: 48px;"></i>\n                    <p class="mt-3 mb-0">Failed to delete template</p>\n                    <p class="text-muted small">${e.message}</p>\n                </div>\n            `,i.disabled=!1,i.innerHTML='<i class="bi bi-trash-fill me-2"></i>Try Again'}},{once:!0})}(e.id,e.title)}),0===o&&r.classList.add("selected"),n.appendChild(r)}),f()}(t,"my-custom-templates"===e),t.length>0?h(t[0]):h(null);const n="my-custom-templates"===e||"basictemplate"===e;document.querySelectorAll("#categoryButtons .category-button").forEach(t=>{n?t.classList.remove("btn-selected"):t.classList.toggle("btn-selected",t.dataset.categoryId===e)});const o=document.getElementById("basicTemplatesBtn");o&&o.classList.toggle("btn-selected","basictemplate"===e);const s=document.getElementById("myCustomTemplatesBtn");s&&s.classList.toggle("btn-selected","my-custom-templates"===e),console.log(`📂 Category selected: ${e}, templates loaded: ${t.length}`)}catch(t){console.error(`Error selecting category ${e}:`,t),function(e,t){document.querySelector(".image-gallery").innerHTML=`\n        <div class="alert alert-warning" role="alert">\n            <i class="bi bi-exclamation-triangle"></i> Failed to load templates for ${b(e)}: ${t}\n            <br>\n            <button type="button" class="btn btn-sm btn-outline-primary mt-2" onclick="window.retrySelectCategory('${e}')">Retry</button>\n        </div>`}(e,t.message)}}function f(){e(document.getElementById("templateGalleryContainer"),document.querySelector("#templateGalleryContainer .image-gallery"))}function h(e){if(!e||!e.id)return u=null,document.querySelectorAll(".template-container").forEach(e=>{e.classList.remove("selected")}),null;return"basictemplate"===e.category&&window.userSubscription&&!window.userSubscription.isPaying?(function(){const e=document.getElementById("appModal"),t=document.getElementById("appModalLabel"),n=document.getElementById("appModalBody"),o=document.getElementById("appModalFooter");if(!e)return void console.error("Modal element not found");t.textContent="Premium Feature",n.innerHTML='\n        <div class="text-center">\n            <div class="mb-3">\n                <i class="bi bi-lock-fill" style="font-size: 48px; color: #FFD700;"></i>\n            </div>\n            <h5 class="mb-3">Base Template</h5>\n            <p class="mb-3">\n                    The Base Template provide a clean and simple format for building custom templates.\n            </p>\n            <p class="text-muted">\n                <strong>This feature is available on all paid plans.</strong>\n            </p>\n        </div>\n    ',o.innerHTML='\n        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Maybe Later</button>\n        <a href="/manage-subscription" class="btn btn-primary">\n            <i class="bi bi-star-fill me-2"></i>Upgrade Now\n        </a>\n    ';new bootstrap.Modal(e).show()}(),null):(u=e.id,e.category&&(d=e.category),document.querySelectorAll(".template-container").forEach(t=>{t.classList.toggle("selected",t.dataset.templateId===e.id)}),u)}async function y(){try{const e=await m();let t=[...new Set(e.map(e=>e.category))];t=t.filter(e=>"basictemplate"!==e),t.sort((e,t)=>l.indexOf(e)-l.indexOf(t));const n=document.getElementById("categoryButtons");n.innerHTML="",t.forEach(e=>{const t=document.createElement("div");t.className="category-container";const o=document.createElement("button");o.className="category-button",o.textContent=b(e),o.dataset.categoryId=e,o.addEventListener("click",()=>g(e)),t.appendChild(o),n.appendChild(t)});let o=d;if(document.getElementById("myCustomTemplatesBtn"))try{const e=await p();e&&e.length>0&&(console.log(`🎨 User has ${e.length} custom template(s), defaulting to My Custom Templates`),o="my-custom-templates")}
1catch(e){console.log("ℹ️ Could not fetch custom templates, using regular default category")}"my-custom-templates"===o||t.includes(o)?g(o):t.length>0&&g(t[0]),function(){const e=document.getElementById("myCustomTemplatesBtn");e&&(console.log("✅ Found My Custom Templates button, attaching click handler"),e.addEventListener("click",e=>{e.preventDefault(),e.stopPropagation(),console.log("🎨 My Custom Templates button clicked"),g("my-custom-templates")}))}(),function(){const e=document.getElementById("basicTemplatesBtn");e&&(console.log("✅ Found Basic Templates button, attaching click handler"),e.addEventListener("click",e=>{e.preventDefault(),e.stopPropagation(),console.log("📄 Basic Templates button clicked"),g("basictemplate")}))}()}catch(t){console.error("Error setting up categories:",t),e=t.message,document.getElementById("categoryButtons").innerHTML=`\n        <div class="alert alert-warning" role="alert">\n            <i class="bi bi-exclamation-triangle"></i> Failed to load categories: ${e}\n            <button type="button" class="btn btn-sm btn-outline-primary ms-2" onclick="window.retrySetupCategories()">Retry</button>\n        </div>`}var e}function b(e){return{resume:"Résumés",business:"Documents",coverletter:"Cover letter",basictemplate:"Basic Documents"}[e]||e.charAt(0).toUpperCase()+e.slice(1)}function w(){return d}function v(){return u}window.retrySetupCategories=y,window.retrySelectCategory=g;const E={emphasis:!0,headings:!0};function x(e,t=E){if(e.nodeType===Node.TEXT_NODE)return e.textContent.replace(/\s+/g," ");if(e.nodeType!==Node.ELEMENT_NODE)return"";const n=e.tagName;let o="";for(const n of e.childNodes)o+=x(n,t);const s=o.trim();if(!s&&!["BR","HR"].includes(n))return o;switch(n){case"STRONG":case"B":return t.emphasis?`**${o}**`:o;case"EM":case"I":return t.emphasis?`*${o}*`:o;case"U":return t.emphasis?`<u>${o}</u>`:o;case"S":case"STRIKE":case"DEL":return t.emphasis?`~~${o}~~`:o}const a=/^H([1-6])$/.exec(n);if(a)return t.headings?`\n${"#".repeat(Number(a[1]))} ${s}\n`:`\n${e.textContent.replace(/\s+/g," ").trim()}\n`;switch(n){case"UL":case"OL":return`\n${o}\n`;case"LI":{const t=e.parentElement,n=t&&"OL"===t.tagName?function(e,t){const n=Array.from(t.children).filter(e=>"LI"===e.tagName),o=t.hasAttribute("reversed"),s=parseInt(t.getAttribute("start"),10);let a=Number.isNaN(s)?o?n.length:1:s;a-=o?-1:1;for(const t of n){const n=parseInt(t.getAttribute("value"),10);if(a=Number.isNaN(n)?a+(o?-1:1):n,t===e)break}const r=(e.style.listStyleType||t.style.listStyleType||"").toLowerCase(),i=e.getAttribute("type")||t.getAttribute("type")||"",l=a>0?String.fromCharCode(97+(a-1)%26).repeat(Math.floor((a-1)/26)+1):String(a);return"a"===i||/lower-(alpha|latin)/.test(r)?`${l}.`:"A"===i||/upper-(alpha|latin)/.test(r)?`${l.toUpperCase()}.`:"i"===i||"lower-roman"===r?`${k(a)}.`:"I"===i||"upper-roman"===r?`${k(a).toUpperCase()}.`:`${a}.`}(e,t):"-",[o,...a]=s.split("\n");if(!/^\d+\.$/.test(n)&&"-"!==n)return`\n${n} ${s}\n\n`;const r=" ".repeat(n.length+1),i=a.map(e=>e.trim()?r+e:e).join("\n");return`${n} ${o}\n${i?i+"\n":""}`}case"TABLE":return`\n${function(e,t=E){const n=[],o=e.querySelectorAll("tr");for(const e of o){const o=[];for(const n of e.children)if("TD"===n.tagName||"TH"===n.tagName){let e="";for(const o of n.childNodes)e+=x(o,t);o.push(e.trim().replace(/\|/g,"\\|").replace(/\n/g," "))}o.length>0&&n.push(o)}if(0===n.length)return"";const s=Math.max(...n.map(e=>e.length)),a=n.map(e=>{for(;e.length<s;)e.push("");return e}),r=[];r.push("| "+a[0].join(" | ")+" |"),r.push("| "+a[0].map(()=>"---").join(" | ")+" |");for(let e=1;e<a.length;e++)r.push("| "+a[e].join(" | ")+" |");return r.join("\n")}(e,t)}\n`;case"BLOCKQUOTE":return`\n${s.split("\n").map(e=>`> ${e}`).join("\n")}\n`}return["P","DIV","SECTION","ARTICLE","HEADER","FOOTER"].includes(n)?`\n${o}\n`:"BR"===n?"\n":"HR"===n?"\n---\n":o}const I=[[1e3,"m"],[900,"cm"],[500,"d"],[400,"cd"],[100,"c"],[90,"xc"],[50,"l"],[40,"xl"],[10,"x"],[9,"ix"],[5,"v"],[4,"iv"],[1,"i"]];function k(e){let t="";for(const[n,o]of I)for(;e>=n;)t+=o,e-=n;return t}function T(e,t=E){const n=function(e){return(new DOMParser).parseFromString(e,"text/html")}(e),o=n.body;if(!o||!o.hasChildNodes())return null;let s="";for(const e of o.childNodes)s+=x(e,t);return s.replace(/\n{3,}/g,"\n\n").replace(/^\n+/,"").replace(/\n+$/,"").trim()}function L(){const e=document.getElementById("outputTypeWord");return!(!e||!e.checked)}function B(){const e=document.getElementById("preserveFormatting");return!(!e||!e.checked)}function C(){if(!L())return B();const e=document.getElementById("keepHeadings");return!(!e||!e.checked)}function S(){return`${B()?1:0}${C()?1:0}`}let $=null;function M(e,t="",n=""){const o=S(),s=e&&"string"==typeof e[o];return $=s?{variants:e,key:o,before:t,after:n}
1:null,s?e[o]:null}function F(){$=null}function _(e){return $.before+$.variants[e]+$.after}function P(e,t){try{localStorage.setItem(e,t)}catch(e){}}function N(e){try{return localStorage.getItem(e)}catch(e){return null}}function H(e,t,n){if(!L()||!$)return;const o=S();if(o!==$.key&&"string"==typeof $.variants[o]){if(e.value!==_($.key)&&!window.confirm("Your text has changed since you pasted or uploaded it. Replace it with the pasted or uploaded text using the new setting?\n\nCancel keeps your text as it is and leaves the setting unchanged."))return t.checked=!t.checked,void P(n,t.checked);$.key=o,e.value=_(o),e.dispatchEvent(new Event("input",{bubbles:!0}))}}function D(e,t){e.checked="true"===N("preserveFormatting"),t&&(t.checked="true"===N("keepHeadings"))}function A(){const e=L();document.getElementById("keepHeadingsToggle")?.classList.toggle("d-none",!e),document.querySelectorAll(".preserve-tip-word").forEach(t=>t.classList.toggle("d-none",!e)),document.querySelectorAll(".preserve-tip-pdf").forEach(t=>t.classList.toggle("d-none",e))}const R=["table of contents","contents","toc","table des matières","table des matieres","sommaire","índice","indice","índice general","indice general","tabla de contenido","tabla de contenidos","contenido","sumario","inhaltsverzeichnis","inhalt","indice generale","sommario","sumário","conteúdo","conteudo","inhoudsopgave","inhoud","spis treści","spis tresci","содержание","оглавление","зміст","içindekiler","İçindekiler","icindekiler","mục lục","innehållsförteckning","innehåll","innholdsfortegnelse","innhold","indholdsfortegnelse","indhold","sisällysluettelo","sisältö","περιεχόμενα","πίνακας περιεχομένων","obsah","tartalomjegyzék","tartalom","المحتويات","جدول المحتويات","الفهرس","תוכן עניינים","תוכן","目录","目錄","目次","목차","차례"].map(function(e){const t=e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/\s+/g,"\\s+");return new RegExp(`^[ \\t]*${t}[ \\t:.\\-:。、]*$`,"imu")}),O="[\\d\\uFF10-\\uFF19]";function q(e){if(!e||e.length<50)return null;for(const t of R){const n=e.match(t);if(n&&"number"==typeof n.index)return{start:n.index,length:n[0].length,kind:"heading"}}const t=e.match(new RegExp(`^[^\\n]*\\.{5,}[ \\t]*${O}+[ \\t]*$`,"mu"));if(t)return z(e,t.index,"content");const n=e.split("\n"),o=new RegExp(`\\s{2,}${O}{1,3}\\s*$`,"u");let s=0,a=null,r=0;for(const e of n){if(e.trim().length>10&&o.test(e)&&(null===a&&(a={start:s,length:e.length}),r++,r>=3))return{...a,kind:"content"};s+=e.length+1}const i=/^(chapter|section|part|appendix)\s+[\divxlc]+.*\d{1,3}\s*$/im,l=new RegExp(i.source,"gim"),c=e.match(l);if(c&&c.length>=2){const t=e.match(i);if(t&&"number"==typeof t.index)return z(e,t.index,"content")}return null}function z(e,t,n){const o=e.lastIndexOf("\n",t-1)+1,s=e.indexOf("\n",t);return{start:o,length:(-1===s?e.length:s)-o,kind:n}}function W(e,t,n,o=!1){const s=[/\.{3,}\s*\d+\s*$/,/\s{2,}\d{1,3}
1\s*$/,/^[ \t]*\d+(\.\d+)*[.)\]]?\s+\S/,/^[ \t]*[ivxlcm]+[.)\]]\s+\S/i,/^[ \t]*(chapter|section|part|appendix|book|volume|article)\b/i,/^[ \t]*[•·▪○●▶►‣⁃\-*]\s+\S/];o&&s.push(/^.{2,100}\s\d{1,3}\s*$/,/(\.\s){3,}\s*\d+\s*$/);const a=e.split("\n");let r=0,i=-1;for(let e=0;e<a.length;e++){const n=r+a[e].length;if(t>=r&&t<=n){i=e;break}r=n+1}if(-1===i)return t+n;let l=i,c=0;for(let e=i+1;e<a.length;e++){const t=a[e].trim();if(""===t){if(c++,c>1)break;continue}if(t.length>120)break;if(!s.some(t=>t.test(a[e])))break;l=e,c=0}let d=0;for(let e=0;e<=l;e++)d+=a[e].length,e<l&&(d+=1);return d}function j(e){const t=document.getElementById("appModal");if(!t)return void console.warn("appModal not found");if(t.classList.contains("show"))return void t.addEventListener("hidden.bs.modal",()=>{const e=document.getElementById("userInput");e&&Q(e.value)},{once:!0});document.getElementById("appModalLabel").textContent="Table of Contents Detected",document.getElementById("appModalBody").innerHTML='\n        <div class="alert alert-warning mb-3">\n            <i class="bi bi-exclamation-triangle-fill me-2"></i>\n            <strong>We found a Table of Contents in your text.</strong>\n        </div>\n        <p>If you don\'t remove it, your final PDF will have <strong>two tables of contents</strong> &mdash; your original one plus the one we generate from your headings.</p>\n        <p class="mb-2"><strong>How this works:</strong></p>\n        <ol class="mb-3">\n            <li>Click <strong>"Show me where it is"</strong> &mdash; we\'ll scroll to and highlight your TOC.</li>\n            <li>Select your full TOC in the text box and delete it.</li>\n            <li>Click the <strong>"Set up auto-TOC"</strong> button that appears, and we\'ll handle the rest (clickable links, accurate page numbers, cover page).</li>\n        </ol>\n        <p class="text-center mt-3 mb-0">\n            <a href="#" id="tocKeepMineLink" class="small text-muted">Keep my TOC and don\'t auto-generate one &mdash; I understand the page numbers may not match</a>\n        </p>\n    ';const n=document.getElementById("appModalFooter");n.style.display="flex";const o=document.getElementById("appModalPrimaryBtn");o.innerHTML='<i class="bi bi-arrow-down-circle me-1"></i> Show me where it is',o.className="btn btn-primary";const s=o.cloneNode(!0);o.parentNode.replaceChild(s,o),s.addEventListener("click",()=>{const n=bootstrap.Modal.getInstance(t);n&&n.hide(),be(),function(){if(document.getElementById(U))return;const e=document.getElementById("userInput");if(!e)return;const t=e.closest(".drag-drop-zone")||e,n=document.createElement("div");n.id=U,n.className="toc-action-banner alert alert-warning d-flex align-items-center justify-content-between flex-wrap mb-2",n.setAttribute("role","status"),n.innerHTML='\n        <div class="me-3 mb-2 mb-md-0">\n            <i class="bi bi-exclamation-triangle-fill me-2"></i>\n            <strong>Delete your highlighted TOC from the text box</strong>, then click here &rarr;\n        </div>\n        <div class="d-flex align-items-center gap-2">\n            <button type="button" class="btn btn-primary btn-sm" id="tocBannerSetupBtn">\n                <i class="bi bi-magic me-1"></i> Set up auto-TOC\n            </button>\n            <button type="button" class="btn-close" id="tocBannerCloseBtn" aria-label="Dismiss"></button>\n        </div>\n    ',t.parentNode.insertBefore(n,t),document.getElementById("tocBannerSetupBtn").addEventListener("click",()=>{!function(){const e=document.getElementById("optionsDashboardCollapse");if(e){bootstrap.Collapse.getOrCreateInstance(e,{toggle:!1}).show()}setTimeout(()=>{const e=document.getElementById("generateToc");e&&!e.checked&&(e.checked=!0,e.dispatchEvent(new Event("change")));const t=document.getElementById("coverPageTextInput");t&&(t.scrollIntoView({behavior:"smooth",block:"center"}),setTimeout(()=>{t.focus(),t.style.transition="box-shadow 0.3s ease",t.style.boxShadow="0 0 10px 3px rgba(13, 110, 253, 0.5)",setTimeout(()=>{t.style.boxShadow=""},2e3)},400))},300)}(),G()}),document.getElementById("tocBannerCloseBtn").addEventListener("click",()=>{V(),G()})}(),setTimeout(()=>function(e){const t=document.getElementById("userInput");if(!t)return;t.scrollIntoView({behavior:"smooth",block:"center"});const n=W(t.value,e.start,e.length);t.focus();try{t.setSelectionRange(e.start,Math.max(n,e.start+e.length))}catch(e){}(function(e,t){const n=getComputedStyle(e);let o=parseFloat(n.lineHeight);isFinite(o)||(o=1.2*parseFloat(n.fontSize)||20);const s=e.value.substring(0,t).split("\n").length-1;e.scrollTop=Math.max(0,s*o-e.clientHeight/3)})(t,e.start),t.classList.remove("toc-pulse"),t.offsetWidth,t.classList.add("toc-pulse"),setTimeout(()=>t.classList.remove("toc-pulse"),2500)}(e),250)});const a=n.querySelector(".btn-secondary");a&&(a.textContent="Close"),setTimeout(()=>{const e=document.getElementById("tocKeepMineLink");e&&e.addEventListener("click",e=>{e.preventDefault(),function(){V();const e=document.getElementById("generateToc");e&&e.checked&&(e.checked=!1,e.dispatchEvent(new Event("change")))}();const n=bootstrap.Modal.getInstance(t);n&&n.hide()})},0);bootstrap.Modal.getOrCreateInstance(t).show()}const U="tocActionBanner";function G(){const e=document.getElementById(U);e&&e.remove()}let K=null;const X=500;function Y(e){return(e||"").slice(0,X)}function V(){const e=document.getElementById("userInput");K=Y(e&&e.value)}function Q(e){if(L())return void ie(e);const t=q(e);if(!t)return K=null,void(e&&e.trim()||G());null!==K&&Y(e)===K||null===document.getElementById(U)&&j(t)}function J(){K=null,G(),le()}const Z="tocWordBanner",ee="tocHighlightLayer";let te=null,ne=null,oe="",se=null;function ae(){return document.getElementById("wordGenerateToc")}function re(){const e=ae();return!(!e||!e.checked)}function ie(e){const t=document.getElementById("userInput");if(!t)return;const n=document.getElementById("textarea-success-overlay");if(n)return void(se||(se=new MutationObserver(()=>{n.isConnected||(se.disconnect(),se=null,ie(t.value))}),se.observe(n.parentNode,{childList:!0})));const o=q(e);if(!o)return K=null,he(),e.trim()?"found"===te&&(te=re()?null:"removed"):te=null,void ce();
1if(null!==K&&Y(e)===K)return void le();const s="found"!==te;te="found",ne={start:o.start,end:Math.max(W(e,o.start,o.length,!0),o.start+o.length)},be(),pe(),ce(),s&&function(){const e=document.getElementById("userInput"),t=document.querySelector(`#${ee} mark`);if(!e||!t)return;const n=t.offsetTop;if(n>=e.scrollTop&&n<e.scrollTop+.75*e.clientHeight)return;e.scrollTop=Math.max(0,n-e.clientHeight/4),fe()}()}function le(){te=null,he(),ce()}function ce(){let e=document.getElementById(Z);const t=re();if(!te||"removed"===te&&t)return e&&e.remove(),void("removed"===te&&(te=null));const n='<button type="button" class="btn btn-primary btn-sm" data-toc-action="setup">\n            <i class="bi bi-magic me-1"></i> Set up auto-TOC\n        </button>',o='<button type="button" class="btn btn-link btn-sm p-0" data-toc-action="keep">It\'s not a TOC</button>';let s,a;if("found"!==te||t?"found"===te?(s="<strong>Automatic table of contents is on.</strong> Delete the highlighted table of contents from the text box so your document doesn't have two.",a=o):(s="<strong>Table of contents removed.</strong> Want an automatic one built from your headings?",a=n):(s="<strong>This looks like a table of contents</strong> (highlighted in the text box). If it is, delete it and set up an automatic one - built from your headings, with page numbers that stay correct.",a=n+o),!e){const t=document.getElementById("userInput");if(!t)return;const n=t.closest(".drag-drop-zone")||t;e=document.createElement("div"),e.id=Z,e.className="toc-action-banner alert alert-warning d-flex align-items-center justify-content-between flex-wrap gap-2 mb-2",e.setAttribute("role","status"),e.addEventListener("click",de),n.parentNode.insertBefore(e,n)}e.innerHTML=`\n        <div class="toc-banner-message">\n            <i class="bi bi-list-ol me-2"></i>${s}\n        </div>\n        <div class="d-flex align-items-center gap-3">\n            ${a}\n            <button type="button" class="btn-close" data-toc-action="dismiss" aria-label="Dismiss"></button>\n        </div>\n    `}function de(e){const t=e.target.closest("[data-toc-action]");if(!t)return;"setup"===t.dataset.tocAction?(!function(){const e=document.getElementById("wordOptionsCollapse");e&&bootstrap.Collapse.getOrCreateInstance(e,{toggle:!1}).show();const t=ae();if(!t)return;t.checked||(t.checked=!0,t.dispatchEvent(new Event("change")));be(),setTimeout(()=>{const e=[t.closest(".form-check"),document.getElementById("wordTocLevelContainer")].filter(Boolean);e[0].scrollIntoView({behavior:"smooth",block:"center"}),e.forEach(e=>{e.classList.remove("toc-setting-glow"),e.offsetWidth,e.classList.add("toc-setting-glow"),setTimeout(()=>e.classList.remove("toc-setting-glow"),2500)})},400)}(),ce()):("found"===te&&V(),le())}const ue=["borderTopWidth","borderRightWidth","borderBottomWidth","borderLeftWidth","paddingTop","paddingRight","paddingBottom","paddingLeft","fontFamily","fontSize","fontWeight","fontStyle","fontVariant","fontStretch","lineHeight","letterSpacing","wordSpacing","textTransform","textIndent","textAlign","tabSize","direction","whiteSpace","overflowWrap","wordBreak"];let me=null;function pe(){const e=document.getElementById("userInput");if(!e||!ne)return void he();let t=document.getElementById(ee);t||(t=document.createElement("div"),t.id=ee,t.className="toc-highlight-layer",t.setAttribute("aria-hidden","true"),t.appendChild(document.createElement("div")),e.after(t),e.addEventListener("scroll",fe,{passive:!0}),me=new ResizeObserver(ge),me.observe(e));const n=e.value,o=document.createElement("mark");o.className="toc-highlight-mark",o.textContent=n.slice(ne.start,ne.end),t.firstElementChild.replaceChildren(document.createTextNode(n.slice(0,ne.start)),o),oe=n,ge()}function ge(){const e=document.getElementById("userInput"),t=document.getElementById(ee);if(!e||!t)return;if(!e.offsetParent)return void(t.style.display="none");t.style.display="";const n=getComputedStyle(e);ue.forEach(e=>{t.style[e]=n[e]});const o=e.offsetWidth-e.clientWidth-parseFloat(n.borderLeftWidth)-parseFloat(n.borderRightWidth);t.style.top=`${e.offsetTop}px`,t.style.left=`${e.offsetLeft}px`,t.style.width=e.offsetWidth-Math.max(0,o)+"px",t.style.height=`${e.offsetHeight}px`,fe()}function fe(){const e=document.getElementById("userInput"),t=document.getElementById(ee);e&&t&&(t.firstElementChild.style.transform=`translate(${-e.scrollLeft}px, ${-e.scrollTop}px)`)}function he(){ne=null;const e=document.getElementById(ee);if(!e)return;const t=document.getElementById("userInput");t&&t.removeEventListener("scroll",fe),me&&(me.disconnect(),me=null),e.remove()}let ye=!1;function be(){if(ye)return;ye=!0;const e=document.createElement("style");e.textContent="\n        @keyframes tocFadeGlow {\n            0%   { box-shadow: 0 0 0 6px rgba(255, 193, 7, 0.85), 0 0 24px 8px rgba(255, 193, 7, 0.55); }\n            100% { box-shadow: 0 0 0 0 rgba(255, 193, 7, 0),   0 0 0 0 rgba(255, 193, 7, 0); }\n        }\n        textarea#userInput.toc-pulse {\n            animation: tocFa
1deGlow 2.4s ease-out 1;\n            border-color: #ffc107 !important;\n        }\n        .toc-action-banner {\n            border-left: 4px solid #ffc107;\n        }\n        .toc-action-banner .btn-close {\n            font-size: 0.75rem;\n        }\n        .toc-highlight-layer {\n            position: absolute;\n            z-index: 2;\n            margin: 0;\n            overflow: hidden;\n            box-sizing: border-box;\n            border-style: solid;\n            border-color: transparent;\n            background: transparent;\n            color: transparent;\n            pointer-events: none;\n        }\n        .toc-highlight-mark {\n            padding: 0;\n            color: transparent;\n            background: rgba(255, 193, 7, 0.35);\n            border-radius: 2px;\n        }\n        .toc-setting-glow {\n            animation: tocFadeGlow 2.4s ease-out 1;\n            border-radius: 6px;\n        }\n    ",document.head.appendChild(e)}function we(e){let t=window.sanitizeInput?window.sanitizeInput(e):e;return t=function(e){const t=/\$\$[\s\S]*?\$\$|\$(?:\\.|[^\n$])*?\$/g;let n,o="",s=0;for(;null!==(n=t.exec(e));
1)o+=e.slice(s,n.index).replace(/\\n/g,"\n").replace(/\\r/g,"\r"),o+=n[0],s=n.index+n[0].length;return o+=e.slice(s).replace(/\\n/g,"\n").replace(/\\r/g,"\r"),o}(t),t.startsWith('"')&&t.endsWith('"')&&(t=t.slice(1,-1)),t}function ve(e){if(!e||"object"!=typeof e)return null;const t={};for(const[n,o]of Object.entries(e))t[n]=we(String(o));return t}function Ee(e,t){const n=document.getElementById("fileInput"),o=document.getElementById("uploadStatus");window.fmInputSource=window.fmInputSource||"paste",window.fmUploadId=window.fmUploadId||null,e.addEventListener("input",()=>{e.value.trim()||(window.fmInputSource="paste",window.fmUploadId=null)});const s=document.querySelector(".drag-drop-zone"),a=document.querySelector(".drag-drop-overlay");function r(t="Processing document...",n=""){i();const o=document.createElement("div");o.id="textarea-processing-overlay",o.style.cssText="\n            position: absolute;\n            top: 0;\n            left: 0;\n            right: 0;\n            bottom: 0;\n            background: rgba(255, 255, 255, 0.95);\n            display: flex;\n            flex-direction: column;\n            align-items: center;\n            justify-content: center;\n            z-index: 10;\n            border-radius: 0.375rem;\n            pointer-events: none;\n        ",o.innerHTML=`\n            <div class="spinner-border text-primary mb-2" role="status" style="width: 2rem; height: 2rem;">\n                <span class="visually-hidden">Processing...</span>\n            </div>\n            <div style="font-weight: 500; color: #495057;">${t}</div>\n            ${n?`<div style="font-size: 0.875rem; color: #6c757d; margin-top: 0.5rem; text-align: center; max-width: 85%;">${n}</div>`:""}\n        `;const s=e.parentElement;"relative"!==s.style.position&&(s.style.position="relative"),s.appendChild(o)}function i(){const e=document.getElementById("textarea-processing-overlay");e&&e.remove()}function l(t,n,o={}){const{details:s="",warningHtml:a="",duration:r=6e3}=o;i(),e.value=n,e.dispatchEvent(new Event("input")),"function"==typeof window.updateTokenCount&&window.updateTokenCount(),function(){if(document.getElementById("textarea-success-overlay-styles"))return;const e=document.createElement("style");e.id="textarea-success-overlay-styles",e.textContent="\n            #textarea-success-overlay .success-body { max-width: 520px; padding: 0 1.25rem; color: #fff; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.35); }\n            #textarea-success-overlay .success-title { font-weight: 700; font-size: 1.15rem; text-align: center; line-height: 1.4; }\n            #textarea-success-overlay .success-details { text-align: left; margin-top: 1rem; line-height: 1.6; }\n            #textarea-success-overlay .success-notice { margin-top: 1.25rem; padding: 0.75rem 1rem; text-align: left; line-height: 1.5; background: rgba(255, 255, 255, 0.15); border: 1px solid rgba(255, 255, 255, 0.35); border-radius: 10px; }\n            #textarea-success-overlay a { color: #fff; font-weight: 700; text-decoration: underline; }\n            #textarea-success-overlay a:hover { text-decoration: none; }\n        ",document.head.appendChild(e)}();const l=document.createElement("div");l.id="textarea-success-overlay",l.style.cssText="\n            position: absolute;\n            top: 0;\n            left: 0;\n            right: 0;\n            bottom: 0;\n            background: linear-gradient(45deg, #00CC44, #4169E1, #8A2BE2);\n            background-size: 200% auto;\n            animation: shimmer 3s ease-in-out infinite;\n            display: flex;\n            flex-direction: column;\n            align-items: center;\n            justify-content: center;\n            z-index: 10;\n            border-radius: 0.375rem;\n            pointer-events: auto;\n            transition: opacity 0.3s ease-out;\n            cursor: pointer;\n        ",l.innerHTML=`\n            <div class="success-body">\n                <div class="success-title">${t}</div>\n                ${s?`<div class="success-details">${s}</div>`:""}\n                ${a?`<div class="success-notice">${a}
1</div>`:""}\n            </div>\n            <div style="font-size: 0.9rem; color: rgba(255, 255, 255, 0.85); margin-top: 1rem; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.35);">Click anywhere to dismiss</div>\n        `;function c(){l.style.opacity="0",setTimeout(()=>{l.remove()},300)}e.parentElement.appendChild(l),l.addEventListener("click",c);const d=setTimeout(c,r);l.addEventListener("click",()=>clearTimeout(d))}function c(e){e.preventDefault(),e.stopPropagation()}function d(e){s.classList.add("drag-over"),a.style.display="flex"}function u(e){s.classList.remove("drag-over"),a.style.display="none"}async function m(e){o.style.display="none",o.className="alert";const t=document.querySelector(".drag-drop-overlay");if(t&&(t.style.display="none"),i(),!e)return p("Please select a file.","alert-warning"),void(n.value="");const s=e.name.toLowerCase(),a=s.endsWith(".md"),c=s.endsWith(".txt")||a,d=s.endsWith(".doc"),u=s.endsWith(".docx"),m=s.endsWith(".pdf");if(!(c||d||u||m))return p("Please select a .txt, .md, .docx, or .pdf file.","alert-warning"),void(n.value="");let g,f;if((d||u||m)&&!localStorage.getItem("hideHeaderFooterModal")&&await new Promise(e=>{const t=document.getElementById("appModal");document.getElementById("appModalLabel").textContent="Document Processing Information",document.getElementById("appModalBody").innerHTML='\n                <div class="mb-3">\n                    <p>📄 <strong>Header & Footer Removal</strong></p>\n                    <p>Our system automatically removes standard-sized headers and footers from your document during text extraction. This helps focus on your main content.</p>\n                    <p><strong>⚠️ Please Note:</strong> Following processing, briefly check approximately the first page of output to ensure no header or footer information remains.</p>\n                </div>\n                <div class="form-check">\n                    <input class="form-check-input" type="checkbox" id="dontShowAgainCheck">\n                    <label class="form-check-label" for="dontShowAgainCheck">\n                        Don\'t show this message again\n                    </label>\n                </div>\n            ';const n=document.getElementById("appModalFooter"),o=t.querySelector(".modal-header .btn-close"),s=n.querySelector(".btn-secondary");o&&(o.style.display="none"),s&&(s.style.display="none"),n.style.display="flex",n.style.justifyContent="center";const a=document.getElementById("appModalPrimaryBtn");a.textContent="Got it, continue",a.className="btn btn-primary";const r=()=>{o&&(o.style.display=""),s&&(s.style.display=""),n.style.justifyContent=""},i=()=>{document.getElementById("dontShowAgainCheck").checked&&localStorage.setItem("hideHeaderFooterModal","true"),a.removeEventListener("click",i),r();const n=bootstrap.Modal.getInstance(t);n&&n.hide(),e()};a.addEventListener("click",i),new bootstrap.Modal(t,{backdrop:"static",keyboard:!1}).show()}),c?(g=2097152,f="File size exceeds 2MB limit for text files."):(g=10485760,f="File size exceeds 10MB limit for document files."),e.size>g)return p(f,"alert-warning"),void(n.value="");try{if(c){r(`Reading ${e.name}...`);const t=await function(e){return new Promise((t,n)=>{const o=new FileReader;o.onload=e=>t(e.target.result),o.onerror=e=>n(e),o.readAsText(e)})}(e),n=window.sanitizeInput?window.sanitizeInput(t):t;window.fmInputSource=a?"md":"txt",window.fmUploadId=L()?await async function(e){try{const t=new FormData;t.append("file",e);const n=await fetch("/api/native-word/source",{method:"POST",body:t,credentials:"include"});return n.ok&&(await n.json()).upload_id||null}catch(e){return null}}(e):null,F(),l(`Successfully processed ${e.name}`,n)}else if(d||u){const t=new FormData;t.append("file",e),B()&&t.append("preserve_formatting","true"),L()&&t.append("keep_headings",C()?"true":"false");const n=e.size>5242880,o=n?"⏱️ Larger file - upload and processing may take a minute or two.":"";r(`Uploading ${e.name}...`,o);const s=new XMLHttpRequest,a=new Promise((o,a)=>{const i=setTimeout(()=>{s.abort(),a(new Error("Upload timeout: File is taking too long to process. This may be due to a slow connection or very large file. Please try again with a smaller file or better internet connection."))},3e5);s.upload.addEventListener("progress",t=>{if(t.lengthComputable&&n){const n=t.loaded/t.total*100,o=(t.loaded/1024/1024).toFixed(1),s=(t.total/1024/1024).toFixed(1);r(`Uploading ${e.name}...`,`📤 ${n.toFixed(0)}% complete (${o}MB / ${s}MB)`)}}),s.upload.addEventListener("load",()=>{r(`Processing ${e.name}...`,"Extracting text and images...")}),s.addEventListener("load",()=>{clearTimeout(i),s.status>=200&&s.status<300?o(s.response):a(new Error(s.responseText||"Failed to extract text from Word document"))}),s.addEventListener("error",()=>{clearTimeout(i),a(new Error("Network error occurred during upload"))}),s.addEventListener("abort",()=>{clearTimeout(i),a(new Error("Upload was cancelled"))}
1),s.open("POST","/extract-word"),s.setRequestHeader("Cache-Control","no-cache"),s.send(t)});try{const e=await a;let t="",n=0,o="",s=null,r=!1,i=null,c=null;try{const a=JSON.parse(e);t=a.text||"",n=parseInt(a.images_extracted)||0,o=a.warning||"",s=a.variants||null,c=a.upload_id||null,r=!0===a.toc_removed,i=parseInt(a.toc_depth,10)||null}catch(n){t=e}if(!t.trim())throw new Error("No text could be extracted from the document");const d=M(ve(s))??we(t);let u="";n>0&&(u=`• ${n} image${n>1?"s":""} extracted to your image library<br>• Image placeholders added to your text<br>• When formatted, placeholders will be replaced with actual images`),r&&(!function(e){const t=document.getElementById("wordTocMaxLevel");t&&Number.isInteger(e)&&t.querySelector(`option[value="${e}"]`)&&(t.value=String(e));const n=ae();n&&!n.checked&&(n.checked=!0,n.dispatchEvent(new Event("change")))}(i),u+=(u?"<br>":"")+"• Your document's table of contents was removed - an automatic one will be built from your headings (you can turn it off in Formatting Options)");const m=o||r?8e3:6e3;window.fmInputSource="docx",window.fmUploadId=c,l("Extraction complete!",d,{details:u,warningHtml:o,duration:m})}catch(e){throw e}}else if(m){const t=new FormData;t.append("file",e);const n=document.getElementById("preserveFormatting");n&&n.checked&&t.append("preserve_formatting","true"),L()&&t.append("keep_headings",C()?"true":"false");const o=e.size>5242880,s=o?"⏱️ Larger file - upload and processing may take a minute or two.":"";r(`Uploading ${e.name}...`,s);const a=new XMLHttpRequest,i=new Promise((n,s)=>{const i=setTimeout(()=>{a.abort(),s(new Error("Upload timeout: File is taking too long to process. This may be due to a slow connection or very large file. Please try again with a smaller file or better internet connection."))},3e5);a.upload.addEventListener("progress",t=>{if(t.lengthComputable&&o){const n=t.loaded/t.total*100,o=(t.loaded/1024/1024).toFixed(1),s=(t.total/1024/1024).toFixed(1);r(`Uploading ${e.name}...`,`📤 ${n.toFixed(0)}% complete (${o}MB / ${s}MB)`)}}),a.upload.addEventListener("load",()=>{r(`Processing ${e.name}...`,"Extracting text and images...")}),a.addEventListener("load",()=>{clearTimeout(i),a.status>=200&&a.status<300?n(a.response):s(new Error(a.responseText||"Failed to extract text from PDF document"))}),a.addEventListener("error",()=>{clearTimeout(i),s(new Error("Network error occurred during upload"))}),a.addEventListener("abort",()=>{clearTimeout(i),s(new Error("Upload was cancelled"))}),a.open("POST","/extract-pdf"),a.setRequestHeader("Cache-Control","no-cache"),a.send(t)});try{const e=await i;let t="",n=0,o="",s=null,a=null;try{const r=JSON.parse(e);t=r.text||"",n=parseInt(r.images_extracted)||0,o=r.warning||"",s=r.variants||null,a=r.upload_id||null}catch(n){t=e}if(!t.trim())throw new Error("No text could be extracted from the document");const r=M(ve(s))??we(t);let c="";n>0&&(c=`• ${n} image${n>1?"s":""} extracted to your image library<br>• Image placeholders added to your text<br>• When formatted, placeholders will be replaced with actual images`);const d=o?8e3:6e3;window.fmInputSource="pdf",window.fmUploadId=a,l("Extraction complete!",r,{details:c,warningHtml:o,duration:d})}catch(e){throw e}}n.value=""}catch(t){console.error("Error processing file:",t),i();let o=`Error processing ${e.name}. `;t.message.includes("No text could be extracted")?o+="No text could be extracted from the document.":t.message.includes("password-protected")?o+="The document is password-protected and cannot be processed.":t.message.includes("corrupted")?o+="The file appears to be corrupted or is not a valid document.":t.message.includes("permission")||t.message.includes("access")||t.message.includes("sharing")||t.message.includes("in use")||t.message.includes("locked")?o+=`The file appears to be locked or in use. Please close ${e.name} in Word, Excel, or any PDF viewer and try again.`:o+=d||u||m?`This often happens when the file is currently open. Please close ${e.name} in Word, Excel, or any PDF viewer and try again.`:"Please try again with a different file.",t.message.includes("permission")||t.message.includes("access")||t.message.includes("sharing")||t.message.includes("in use")||t.message.includes("locked")||d||u||m||(o+=" If you're using cloud storage, make sure the file is synced to your local computer."),p(o,"alert-danger"),n.value=""}}function p(e,t){o.textContent=e,o.className=`alert ${t}`,o.style.display="block"}n.addEventListener("change",e=>m(e.target.files[0])),s&&(["dragenter","dragover","dragleave","drop"].forEach(e
1=>{s.addEventListener(e,c,!1),document.body.addEventListener(e,c,!1)}),["dragenter","dragover"].forEach(e=>{s.addEventListener(e,d,!1)}),["dragleave","drop"].forEach(e=>{s.addEventListener(e,u,!1)}),s.addEventListener("drop",function(t){const n=t.dataTransfer.files[0];e.focus(),m(n)},!1))}"undefined"!=typeof window&&(window.updateTokenCount=function(e,o){if(e=e||document.getElementById("userInput"),o=o||document.getElementById("charCount"),!e||!o)return void console.error("Required elements not found for token count update");const s=parseInt(o.dataset.maxTokens,10)||1e4;let a=t(e.value);const r=a;a>s&&(e.value=e.value.slice(0,s),a=s);const i=a>=s;window.__formatInputTruncated=i,window.__formatFullInputChars=i?Math.max(window.__formatFullInputChars||0,r):0,n(a);const l=document.getElementById("tokenDisplay");l&&(l.textContent=`${a.toLocaleString()} / ${s.toLocaleString()} Characters will be used.`);const c=document.getElementById("fullDocCount");if(c){const e=window.__formatFullInputChars||0;i&&e>s?(c.textContent=`Your full document is ${e.toLocaleString()} characters.`,c.style.display="block"):(c.textContent="",c.style.display="none")}if(i){if(o.style.color="#6d28d9",o.style.fontWeight="bold",!o.querySelector(".warning-message")){const e=Math.max(1,Math.floor(s/2e3)),t=`${e} page${1===e?"":"s"}`,n=window.userSubscription&&!1===window.userSubscription.isLoggedIn,a=document.createElement("span");a.className="warning-message d-block mt-2",a.setAttribute("role","note"),a.style.cssText="padding: 0.75rem 1rem; background-color: #faf5ff; border: 2px dashed #c4b5fd; border-radius: 8px; color: #374151; font-weight: 400;",a.innerHTML=n?`<strong style="color: #6d28d9;">Note:</strong> Only the first ${s.toLocaleString()} characters (about ${t}) will be formatted. You can still click <strong>Format Magic</strong> to format this part now. <a href="/subscribe" style="color: #6d28d9; text-decoration: underline;">Sign up</a> to format longer documents and unlock more features.`:`<strong style="color: #6d28d9;">Note:</strong> Only the first ${s.toLocaleString()} characters (about ${t}) will be formatted, the maximum your current plan allows per job. You can still click <strong>Format Magic</strong> to format this part now. Higher plans format more per job. <a href="/manage-subscription" style="color: #6d28d9; text-decoration: underline;">Upgrade your subscription</a>.`,o.appendChild(a);const r=document.getElementById("tokenDashboardCollapse");if(r&&!r.classList.contains("show"))if("undefined"!=typeof bootstrap&&bootstrap.Collapse)(bootstrap.Collapse.getInstance(r)||new bootstrap.Collapse(r)).show();else{r.classList.add("show");const e=document.querySelector('button[data-bs-target="#tokenDashboardCollapse"]');e&&(e.classList.remove("collapsed"),e.setAttribute("aria-expanded","true"))}}}else{o.style.color="",o.style.fontWeight="";const e=o.querySelector(".warning-message");e&&e.remove()}}),window.initTOCDetection=function(){const e=document.getElementById("userInput");if(!e)return void console.warn("TOC Detection: #userInput not found");e.addEventListener("paste",()=>{setTimeout(()=>Q(e.value),100)});const t=function(e,t){let n;return function(...o){clearTimeout(n),n=setTimeout(()=>e(...o),t)}}(()=>Q(e.value),800);e.addEventListener("input",t),e.addEventListener("input",()=>{L()&&function(e){if(!ne)return;const t=oe,n=Math.min(t.length,e.length);let o=0;for(;o<n&&t.charCodeAt(o)===e.charCodeAt(o);)o++;let s=0;for(;s<n-o&&t.charCodeAt(t.length-1-s)===e.charCodeAt(e.length-1-s);)s++;const a=t.length-s,r=e.length-s,i=(n,s)=>n<=o?n:n>=a?n+e.length-t.length:s?r:o,l=i(ne.start,!1),c=i(ne.end,!0);c<=l?he():(ne={start:l,end:c},pe())}(e.value)});const n=ae();n&&n.addEventListener("change",ce),document.querySelectorAll('input[name="outputType"]').forEach(t=>{t.addEventListener("change",()=>{J(),L()&&Q(e.value)})})};let xe=null;function Ie(){return xe=xe||import("./chunks/pdf-mode-DHmwzcP6.js"),xe}window.ensurePdfMode=Ie,window.replaceImageMarkers=async function(e){const t=/\[IMAGE:([^:\]]+)(?::width=([^:\]]+))?(?::height=([^:\]]+))?\]/g,n=[];let o;for(;null!==(o=t.exec(e));
1){let e=o[1];e&&(e=e.replace(/<\/?[^>]+(>|$)/g,""),e=e.trim()),n.push({fullMatch:o[0],markerId:e,width:o[2]||"auto",height:o[3]||"auto"})}if(0===n.length)return e;const s=e=>{let t="display: block; margin-left: auto; margin-right: auto;";if("auto"!==e.width&&e.width){t+=parseInt(e.width)>700?" width: 700px; height: auto;":` width: ${e.width}px; height: auto;`}return t},a={"sample-logo":"/static/images/fm-logo-419x291.webp"};let r=e;const i=[];for(const e of n){const t=a[e.markerId];if(t){const n=`<img src="${t}" alt="Sample image" style="${s(e)}" data-fm-styled="true" />`;r=r.replace(e.fullMatch,n)}else i.push(e)}if(0===i.length)return r;if(!window.currentUserId)return r;try{const e=await fetch("/api/user-images",{method:"GET",credentials:"include"});if(!e.ok)return console.warn("Failed to fetch user images for marker replacement"),r;const t=await e.json();for(const e of i){const n=t.find(t=>t.title&&t.title.includes(`[ID:${e.markerId}]`)||t.filename&&t.filename.includes(`extracted_${e.markerId}`));if(n){const t=`<img src="${n.direct_url}" alt="Extracted image ${e.markerId}" style="${s(e)}" data-fm-styled="true" />`;r=r.replace(e.fullMatch,t)}else console.warn(`No matching image found for marker: ${e.markerId}`),r=r.replace(e.fullMatch,`<p><em>[Image ${e.markerId} not found in library]</em></p>`)}return r}catch(e){return console.error("Error replacing image markers:",e),r}},document.addEventListener("DOMContentLoaded",function(){o(),r(),function(){const e=new URLSearchParams(window.location.search),t=e.get("plan");if(console.log("URL params:",e.toString()),console.log("Plan from URL:",t),t){const e=document.getElementById("plan");e?(e.value=t,console.log("Plan set in input:",e.value)):console.log("Plan input element not found")}else console.log("No plan found in URL")}();const e=document.getElementById("buy-tokens-btn");e?(console.log("Buy tokens button found, adding event listener"),e.addEventListener("click",function(e){console.log("Buy tokens button clicked"),e.preventDefault(),s()})):console.log("Buy tokens button NOT found");const t=document.getElementById("saveDocument");if(t){const p=localStorage.getItem("saveDocumentPreference");t.checked=null===p||"true"===p,t.addEventListener("change",function(){localStorage.setItem("saveDocumentPreference",this.checked)})}const n=document.getElementById("userInput"),i=document.getElementById("charCount"),l=document.getElementById("charCount");try{l&&parseInt(l.dataset.maxTokens,10);const g=document.getElementById("userInput");g&&function(e){e.addEventListener("keydown",function(e){if(e.ctrlKey||e.metaKey){let t=!1;switch(e.key.toLowerCase()){case"b":a("bold"),t=!0;break;case"i":a("italic"),t=!0;break;case"1":case"2":case"3":case"4":case"5":a(`heading${e.key}`),t=!0;break;case"l":a("link"),t=!0;break;case"p":a("pagebreak"),t=!0}t&&e.preventDefault()}})}(g),function(){const e=document.getElementById("sampleTextLink"),t=document.getElementById("userInput");e&&t&&e.addEventListener("click",function(e){e.preventDefault();const n=c[d];n&&fetch(n,{cache:"no-cache"}).then(e=>e.text()).then(e=>{window.fmInputSource="sample",window.fmUploadId=null,t.value=e,t.dispatchEvent(new Event("input"))}).catch(e=>console.error("Error loading sample text:",e))})}(),n&&l&&Ee(n),function(){const e=document.getElementById("userInput"),t=document.getElementById("preserveFormatting"),n=document.getElementById("keepHeadings");e&&t?(D(t,n),A(),document.querySelectorAll('input[name="outputType"]').forEach(e=>{e.addEventListener("change",()=>{D(t,n),A()})}),t.addEventListener("change",()=>{P("preserveFormatting",t.checked),H(e,t,"preserveFormatting")}),n?.addEventListener("change",()=>{P("keepHeadings",n.checked),H(e,n,"keepHeadings")}),e.addEventListener("input",()=>{e.value.trim()||F()}),e.addEventListener("paste",t=>{const n=L();if(!n&&!B())return;const o=t.clipboardData.getData("text/html");if(!o)return;if(!function(e){return!!/<(strong|b|em|i|u|s|strike|del|h[1-6]|ul|ol|li|table|blockquote)\b/i.test(e)}(o))return;const s={};if(n)for(const e of["00","01","10","11"])s[e]=T(o,{emphasis:"1"===e[0],headings:"1"===e[1]});const a=n?s[S()]:T(o);if(!a)return;t.preventDefault();const r=e.selectionStart,i=e.selectionEnd,l=e.value.substring(0,r),c=e.value.substring(i);e.value=l+a+c,n?M(s,l,c):F();const d=r+a.length;e.setSelectionRange(d,d),e.dispatchEvent(new Event("input",{bubbles:!0}))}
1),console.log("Preserve Formatting: initialized")):console.warn("Preserve Formatting: required elements not found")}()}catch(f){}if(n){const h=window.matchMedia("(max-width: 575.98px), ((max-width: 1024px) and (max-height: 575.98px))");n.style.setProperty("height",h.matches?"50svh":"70svh","important");const b=document.querySelector(".drag-drop-zone"),w=document.querySelector(".drag-drop-overlay");if(b&&w){function E(){/\S/.test(n.value)&&(w.style.display="none")}E(),n.addEventListener("input",E),n.addEventListener("paste",()=>setTimeout(E,10))}const v=document.getElementById("textareaFullscreenBtn");if(v&&b){const x='<i class="bi bi-arrows-fullscreen"></i>',I='<i class="bi bi-fullscreen-exit"></i>';function k(){b.classList.remove("is-fullscreen"),document.body.style.overflow="",v.innerHTML=x,v.setAttribute("aria-label","Fullscreen"),v.setAttribute("title","Fullscreen")}v.addEventListener("click",()=>{b.classList.contains("is-fullscreen")?k():(b.classList.add("is-fullscreen"),document.body.style.overflow="hidden",v.innerHTML=I,v.setAttribute("aria-label","Exit fullscreen"),v.setAttribute("title","Exit fullscreen"))}),document.addEventListener("keydown",e=>{"Escape"===e.key&&b.classList.contains("is-fullscreen")&&k()})}}if(n&&i){let C=null;n.addEventListener("input",function(){const e=this;clearTimeout(C),C=setTimeout(function(){"function"==typeof window.updateTokenCount&&window.updateTokenCount(e,i)},150)})}document.getElementById("categoryButtons"),document.getElementById("chooseTemplateSection"),document.querySelector("#templateCarousel .carousel-inner"),document.getElementById("selectedTemplateDisplay"),document.getElementById("selectedTemplateImage"),document.getElementById("selectedTemplateTitle"),document.querySelector(".image-gallery"),document.getElementById("templateGalleryContainer"),document.getElementById("sampleTextLink");var u=document.getElementById("verificationAlert");u&&setTimeout(function(){new bootstrap.Alert(u).close()},5e3),window.isProcessing=!1,document.getElementById("textForm").addEventListener("submit",async function(e){if(e.preventDefault(),window.__wordMode&&window.__wordMode.active)return J(),void window.__wordMode.handleSubmit();const t=document.getElementById("outputTypeWord");if(t&&t.checked){const e=Date.now();for(;t.checked&&(!window.__wordMode||!window.__wordMode.active);){if(Date.now()-e>1e4)return void window.alert("Word output could not be loaded. Please try again.");await new Promise(e=>setTimeout(e,100))}if(window.__wordMode&&window.__wordMode.active)return J(),void window.__wordMode.handleSubmit()}try{const e=await Ie();await e.handlePdfSubmit(this)}catch(e){console.error("PDF mode failed to load:",e),window.alert("Something went wrong loading the formatter. Please refresh the page and try again.")}});const m=document.getElementById("outputTypePdf");m?(m.addEventListener("change",function(){this.checked&&Ie()}),m.checked&&Ie()):document.getElementById("textForm")&&Ie(),y(),document.addEventListener("click",function(e){var t=document.getElementById("navbarNav"),n=document.querySelector(".navbar-toggler");!t.classList.contains("show")||t.contains(e.target)||n.contains(e.target)||(t.classList.remove("show"),n.setAttribute("aria-expanded","false"))})});export{v as a,w as g,J as r};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.