1function Y(t){const e=t.route??(typeof window<"u"?window.location.pathname:void 0);return{...t,route:e}}function m(t,e={}){if(typeof window>"u")return;const n=Y(e);window.posthog&&window.posthog.capture(t,n),window.gtag&&window.gtag("event",t,n)}function Q(t){return/^https?:\/\//i.test(t)}function L(t){const e=t?.trim();return e&&Q(e)?e:null}function q(t,e){if(typeof window>"u")return;const n=L(t);if(!n)return;m("checkout_opened",{source:e?.source,trigger:e?.trigger,checkoutUrl:n,destination:n,plan:e?.plan,variant:e?.variant,userState:e?.userState,hadPriorSuccessfulRun:e?.hadPriorSuccessfulRun,flowId:e?.flowId});const r=window.LemonSqueezy;if(r&&r.Url&&typeof r.Url.Open=="function"){r.Url.Open(n);return}window.open(n,"_blank","noopener,noreferrer")}const R=["pdf.merge","pdf.split","pdf.compress"],C=[...R,"pdf.ocr","pdf.rotate","pdf.delete_pages","pdf.edit","pdf.to_image","office.convert","pdf.protect.encrypt","pdf.protect.unlock","pdf.redact.verify"],F=[...C],H=new Set(F);function V(t,e){const n=Array.isArray(t)?t:[],i=Array.from(new Set(n.filter(o=>typeof o=="string"))).filter(o=>H.has(o)),s=e==="pro"||e==="trial"?new Set(C):new Set(R);return i.filter(o=>s.has(o))}function y(t){return[...t==="pro"||t==="trial"?C:R]}function X(t){return t==="pro"?"pro":t==="trial"?"trial":"basic"}function G(t,e){return t==="free"?e==="basic"?"free":null:t==="pro_monthly"||t==="pro_yearly"||t==="pro_lifetime"?e==="pro"||e==="trial"?t:null:t==null||t===""?W(e):null}function W(t){return t==="pro"||t==="trial"?"pro_monthly":"free"}const c="localpdf_trial_start",h="localpdf_trial_state",b="localpdf_trial_used",I=4320*60*1e3,Z=3600*1e3;let A=null,g=null;const $="localpdf_db",f="trial_store",T="trial_start_time";async function U(){return new Promise((t,e)=>{if(typeof indexedDB>"u")return e(new Error("IndexedDB is not supported"));const n=indexedDB.open($,1);n.onupgradeneeded=()=>{const r=n.result;r.objectStoreNames.contains(f)||r.createObjectStore(f)},n.onsuccess=()=>t(n.result),n.onerror=()=>e(n.error)})}async function ee(t){try{const e=await U();return new Promise((n,r)=>{const o=e.transaction(f,"readonly").objectStore(f).get(t);o.onsuccess=()=>n(o.result),o.onerror=()=>r(o.error)})}catch{return null}}async function P(t,e){try{const n=await U();return new Promise((r,i)=>{const u=n.transaction(f,"readwrite").objectStore(f).put(e,t);u.onsuccess=()=>r(),u.onerror=()=>i(u.error)})}catch{}}async function te(){if(typeof window>"u"||!window.indexedDB)return;const t=localStorage.getItem(c),e=await ee(T);if(e===-1){t&&(localStorage.removeItem(c),localStorage.removeItem(h)),localStorage.setItem(b,"true");return}t&&!e?await P(T,Number(t)):!t&&e&&localStorage.setItem(c,String(e))}function l(){if(typeof localStorage>"u")return{isActive:!1,startedAt:null,endsAt:null,daysRemaining:0,hoursRemaining:0,isExpiredButNotTracked:!1,trialAvailable:!0};const t=localStorage.getItem(b)==="true",e=localStorage.getItem(h),n=localStorage.getItem(c);if(t)return{isActive:!1,startedAt:n?Number(n):null,endsAt:n?Number(n)+I:null,daysRemaining:0,hoursRemaining:0,isExpiredButNotTracked:!1,trialAvailable:!1};if(e==="expired")return{isActive:!1,startedAt:n?Number(n):null,endsAt:n?Number(n)+I:null,daysRemaining:0,hoursRemaining:0,isExpiredButNotTracked:!0,trialAvailable:!1};if(!n)return{isActive:!1,startedAt:null,endsAt:null,daysRemaining:0,hoursRemaining:0,isExpiredButNotTracked:!1,trialAvailable:!0};const r=Number(n);if(Number.isNaN(r))return localStorage.removeItem(c),{isActive:!1,startedAt:null,endsAt:null,daysRemaining:0,hoursRemaining:0,isExpiredButNotTracked:!1,trialAvailable:!0};const i=r+I,s=Date.now();if(s>=i)return localStorage.setItem(h,"expired"),{isActive:!1,startedAt:r,endsAt:i,daysRemaining:0,hoursRemaining:0,isExpiredButNotTracked:!0,trialAvailable:!1};const o=i-s;return{isActive:!0,startedAt:r,endsAt:i,daysRemaining:Math.floor(o/(1440*60*1e3)),hoursRemaining:Math.floor(o%(1440*60*1e3)/(3600*1e3)),isExpiredButNotTracked:!1,trialAvailable:!1}}function ne(t){A=t,E()}function E(){if(typeof window>"u")return;g!==null&&(clearTimeout(g),g=null);const t=l();if(t.isExpiredButNotTracked){A?.();return}if(!t.isActive||t.endsAt===null)return;const e=t.endsAt-Date.now();if(e<=0){l().isExpiredButNotTracked&&A?.();return}g=setTimeout(()=>{if(g=null,l().isExpiredButNotTracked){A?.();return}E()},Math.min(e+250,Z))}function re(){if(typeof localStorage<"u"&&localStorage.getItem(b)==="true")return l();const t=Date.now();localStorage.setItem(c,String(t)),localStorage.removeItem(h),P(T,t).catch(()=>{});const e=l();return E(),e}function S(){localStorage.removeItem(c),localStorage.removeItem(h),localStorage.setItem(b,"true"),P(T,-1).catch(()=>{})}const w={userId:"local-user",plan:"basic",entitlements:y("basic")};function B(t,e=!1){const n=e?t:t.replace(/-/g,"+").replace(/_/g,"/"),r=n.padEnd(n.length+(4-n.length%4)%4,"=");return typeof Buffer<"u"?Buffer.from(r,"base64").toString("binary"):atob(r)}function x(t){const e=B(t);if(typeof Buffer<"u")return Buffer.from(e,"binary").toString("utf8");const n=new Uint8Array(e.length);for(let r=0;r<e.length;r++)n[r]=e.charCodeAt(r);return new TextDecoder().decode(n)}class ie{constructor(e,n){this.storageKey=e,this.jwtPublicKeyPem=n}currentContext=w;listeners=new Set;getContext(){return this.currentContext}subscribe(e){return this.listeners.add(e),()=>this.listeners.delete(e)}notify(){for(const e of this.listeners)e(this.currentContext)}async initialize(){typeof localStorage<"u"&&await te(),ne(()=>{l().isExpiredButNotTracked&&(m("trial_expired",{source:"trial_watch"}),S(),typeof localStorage<"u"&&!localStorage.getItem(this.storageKey)&&(this.currentContext=w,this.notify()))}),E();let e=l();e.isExpiredButNotTracked&&(m("trial_expired",{source:"billing_init"}),S(),e=l());const n=typeof localStorage<"u"?localStorage.getItem(this.storageKey):null;if(!n){e.isActive?this.currentContext={userId:"local-user",plan:"pro",entitlements:y("trial")}:this.currentContext=w,this.notify();return}let r=n,i=await this.verifyToken(r);if(!i){const s=await this.refreshBillingToken(r).catch(()=>null);
1s&&(i=await this.verifyToken(s),i&&(r=s,typeof localStorage<"u"&&localStorage.setItem(this.storageKey,r)))}if(!i){typeof localStorage<"u"&&localStorage.removeItem(this.storageKey),e.isActive?this.currentContext={userId:"local-user",plan:"pro",entitlements:y("trial")}:this.currentContext=w,this.notify();return}this.currentContext={userId:"local-user",plan:i.plan,entitlements:i.entitlements},(e.isActive||e.isExpiredButNotTracked)&&(m("trial_convert",{trialDaysRemaining:e.daysRemaining,source:"token_verified_init"}),S()),this.notify();try{const s=r.split("."),o=JSON.parse(x(s[1])),u=Math.floor(Date.now()/1e3);typeof o.exp=="number"&&o.exp-u<7200*60&&this.refreshBillingToken(r).then(async d=>{d&&await this.saveToken(d)}).catch(()=>{})}catch{}}async saveToken(e){const n=await this.verifyToken(e);if(!n)return!1;const r=l(),i=r.isActive||r.isExpiredButNotTracked;return typeof localStorage<"u"&&(localStorage.setItem(this.storageKey,e),i&&(m("trial_convert",{trialDaysRemaining:r.daysRemaining,source:"manual_save"}),S())),this.currentContext={userId:"local-user",plan:n.plan,entitlements:n.entitlements},this.notify(),!0}startTrial(){re(),this.currentContext={userId:"local-user",plan:"pro",entitlements:y("trial")},this.notify()}async refreshBillingToken(e){try{const n=await fetch("/api/billing/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:e})});if(!n.ok)return null;const r=await n.json();if(r.success&&typeof r.token=="string")return r.token}catch(n){console.error("Error in refreshBillingToken:",n)}return null}async verifyToken(e){try{if(!this.jwtPublicKeyPem?.trim())return null;const n=e.split(".");if(n.length!==3)return null;const r=JSON.parse(x(n[0])),i=JSON.parse(x(n[1])),s=Uint8Array.from(B(n[2]),k=>k.charCodeAt(0));if(r.alg!=="RS256"||r.typ!=="JWT")return null;const o=Math.floor(Date.now()/1e3);if(typeof i.exp!="number"||i.exp<=o||typeof i.iat!="number"||i.iat>o+300||i.nbf!==void 0&&(typeof i.nbf!="number"||i.nbf>o+300)||i.iss!=="localpdf-billing"||i.aud!=="localpdf-v6"||typeof i.sub!="string"||i.sub.trim().length===0)return null;
1const d=this.jwtPublicKeyPem.replace(/\\n/g,` 2`).replace(/-----BEGIN PUBLIC KEY-----|-----END PUBLIC KEY-----|\s+/g,"");if(!d)return null;const O=Uint8Array.from(B(d,!0),k=>k.charCodeAt(0)),v=globalThis.crypto;if(!v?.subtle)return null;const j=await v.subtle.importKey("spki",O,{name:"RSASSA-PKCS1-v1_5",hash:"SHA-256"},!1,["verify"]),J=new TextEncoder().encode(`${n[0]}.${n[1]}`);if(!await v.subtle.verify("RSASSA-PKCS1-v1_5",j,s,J))return null;const p=X(i.plan);if(p==="trial"||!G(i.tier,p))return null;const D=V(i.entitlements,p),z=y(p);return{plan:p,entitlements:D.length>0?D:z}}catch{return null}}}const oe=new ie("v6_subscription_jwt",`-----BEGIN PUBLIC KEY----- 3MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5xPX8DuQ2LNTRswlSiYh 4OFJhnzUdnxKz6twJ5uen63ol36kmfHphA6RDrDuFbNl5/zHj6mDHwRCquMHIk5LJ 5ddZQrfl8JxL4eWi1yBvGxpUUDvixmyg+KQSSiwAjI7tiui41tXQyEimLgl5MJtez 6rMBurruU3dfBtcwg2TsoILKl/oA8rymudPCSl3KzJBhnpbunSiuDVU1wVDfvUwkj 7BiFv96QT6N2rYNV0J7E/kkK0ZP3uTibDn8EXtesdnV9LPQkLlXlib+zMvYqk8+1/ 8LS0P1vLRU+fX5y0fY5XvQA236JlnaQgNSrBSdS4ZCIp/ct/DoJksG9W2FHX0z/gf 9gwIDAQAB 10-----END PUBLIC KEY-----`);function K(t,e){const n=document.getElementById(t);if(!n)return;const r=L(n.getAttribute("data-checkout-url")??void 0);n.addEventListener("click",()=>{if(r){q(r,{source:"pricing_page",trigger:t,plan:"pro",variant:e,userState:"local",hadPriorSuccessfulRun:!1,flowId:t});return}console.error("Missing or invalid LemonSqueezy checkout URL"),alert("Billing configuration is missing. Please contact support.")})}K("buy-pro-lifetime","lifetime");K("buy-pro-monthly","monthly");const N=document.getElementById("restore-license-btn"),_=document.getElementById("license-key-input"),a=document.getElementById("restore-status");async function M(){const t=_?.value?.trim();if(!t){a&&(a.className="status-message error",a.textContent="Enter your license key to restore Pro access."),_?.focus();return}N?.toggleAttribute("disabled",!0),a&&(a.className="status-message",a.textContent="Restoring...");try{const e=await fetch("/api/billing/restore",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({licenseKey:t})}),n=await e.json();if(e.ok&&n.token){if(!await oe.saveToken(n.token))throw new Error("Failed to verify subscription token locally");a&&(a.className="status-message success",a.textContent="License restored successfully. Redirecting to app..."),setTimeout(()=>{window.location.assign("/app")},1800);return}throw new Error(n.error||"Failed to restore license")}catch(e){a&&(a.className="status-message error",a.textContent=e?.message||"Restore failed")}finally{N?.toggleAttribute("disabled",!1)}}N?.addEventListener("click",M);_?.addEventListener("keydown",t=>{t.key==="Enter"&&(t.preventDefault(),M())});
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.