extract-pdf 0.1.260 → 0.1.261

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- function t(t){for(;32===t.charCodeAt(0);)t=t.substring(1,t.length);return t}function e(t){for(;32===t.charCodeAt(t.length-1);)t=t.substring(0,t.length-1);return t}function s(t){return t>=48&&t<=57}function n(t){for(var e=0;e<t.length;e++)if(!s(t.charCodeAt(e)))return!1;return!0}function o(t,e){const s=e.charCodeAt(0);for(var n=0;n<t.length;n++)if(t.charCodeAt(n)!==s)return!1;return!0}function r(t){return function(t){const e=[];for(var s=0;s<t.length;s++)e.push(t.charCodeAt(s));return e}(t=t.toUpperCase()).filter(t=>32!==t&&9!==t&&46!==t)}function a(t){if(t.length>1)return!1;const e=t.charAt(0);return"-"===e||"•"===e||"–"===e}function i(t){return/^[\s]*[-•–][\s].*$/g.test(t)}function h(t){return t.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function l(t,e){const s=new Set(t.toUpperCase().split(" ")),n=new Set(e.toUpperCase().split(" "));return new Set([...s].filter(t=>n.has(t))).size/Math.max(s.size,n.size)}var c=(t,e,s)=>Math.floor(t/e*s),m=(s,o,r)=>{for(const{str:a}of s){const s=e(t(a));n(s)&&(o[r]||(o[r]=[]),o[r].push(Number(s)))}return o},u=(t,e,s)=>{const n=c(1,6,s.length),o=c(5,6,s.length),r=m(s.slice(0,n),t,e);return m(s.slice(o),r,e)},p=t=>{let e=0;const s=Object.keys(t);if(0!==s.length&&1!==s.length)for(let n=0;n<s.length-1;n++){const o=t[s[n]],r=t[s[n+1]],a=e;for(let t=0;t<o.length&&e<2;t++)for(let a=0;a<r.length&&e<2;a++){const i=Number(s[n+1])-Number(s[n]);(o[t]+1===r[a]||i>1&&o[t]+i===r[a])&&e++}let i=n>0?Object.entries(t)[n-1]:Object.entries(t)[n];if(a===e)e=0,i=Object.entries(t)[n];else if(e>=2)return{pageIndex:Number(i[0]),pageNum:i[1][0]}}},f=(t,e)=>{const s={items:[...t.items]},n=c(1,6,s.items.length),o=c(5,6,s.items.length);return s.items=s.items.filter((t,r)=>{const a=r>0&&r<n,i=r>o&&r<s.items.length;return a||i?Number(t.str)!==Number(e):t}),s},d=class t{type;annotation;parsedElements;constructor(e){if(this.constructor===t)throw new TypeError("Can not construct abstract class.");this.type=e.type??null,this.annotation=e.annotation??null,this.parsedElements=e.parsedElements??null}},g=class extends d{x;y;width;height;text;font;lineFormat;unopenedFormat;unclosedFormat;constructor(t){super(t),this.x=t.x,this.y=t.y,this.width=t.width,this.height=t.height,this.text=t.text,this.font=t.font,this.lineFormat=t.lineFormat??null,this.unopenedFormat=t.unopenedFormat??null,this.unclosedFormat=t.unclosedFormat??null}},y=class{index;items;constructor(t){this.index=t.index,this.items=t.items||[]}};async function w(t,e={}){const s=e.timeout?1e3*e.timeout:1e4,n=new AbortController,o=setTimeout(()=>n.abort(),s);try{const s=await fetch(t,{signal:n.signal});if(clearTimeout(o),!s.ok)throw new Error(`HTTP ${s.status}`);return"arraybuffer"===e.responseType?await s.arrayBuffer():await s.text()}catch(r){throw clearTimeout(o),r}}var x=class t{name;itemType;constructor(e,s){if(this.constructor===t)throw new TypeError("Can not construct abstract class.");if(this.transform===t.prototype.transform)throw new TypeError("Please implement abstract method 'transform()'.");this.name=e,this.itemType=s}transform(t){throw new TypeError("Do not call abstract method foo from child.")}completeTransform(t){return t.messages=[],t}},E=class{category;color;constructor(t){this.category=t.category,this.color=t.color}},T=new E({category:"Added",color:"green"}),v=new E({category:"Removed",color:"red"}),b=new E({category:"Unchanged",color:"brown"}),L=new E({category:"Detected",color:"green"}),O=new E({category:"Modified",color:"green"}),I=class t extends x{constructor(e){if(super(e,g.name),this.constructor===t)throw new TypeError("Can not construct abstract class.")}completeTransform(t){return t.messages=[],t.pages.forEach(t=>{t.items=t.items.filter(t=>!t.annotation||t.annotation!==v),t.items.forEach(t=>t.annotation=null)}),t}},S=class{pages;globals;messages;constructor(t){this.pages=t.pages||[],this.globals=t.globals||{},this.messages=t.messages||[]}},k=class{string;type;format;constructor(t){this.string=t.string,this.type=t.type??null,this.format=t.format??null}},C=class extends d{x;y;width;height;words;constructor(t){super(t),this.x=t.x??0,this.y=t.y??0,this.width=t.width??0,this.height=t.height??0,this.words=t.words||[],t.text&&!t.words&&(this.words=t.text.split(" ").filter(t=>t.trim().length>0).map(t=>new k({string:t})))}text(){return this.wordStrings().join(" ")}wordStrings(){return this.words.map(t=>t.string)}},F=class t{results;stash;constructor(){if(this.constructor===t)throw new TypeError("Can not construct abstract class.");this.results=[],this.stash=[]}consumeAll(t){t.forEach(t=>this.consume(t))}consume(t){this.shouldStash(t)?(this.matchesStash(t)||this.flushStash(),this.pushOnStash(t)):(this.stash.length>0&&this.flushStash(),this.results.push(t))}pushOnStash(t){this.onPushOnStash(t),this.stash.push(t)}complete(){return this.stash.length>0&&this.flushStash(),this.results}matchesStash(t){if(0===this.stash.length)return!0;const e=this.stash[this.stash.length-1];return this.doMatchesStash(e,t)}flushStash(){this.stash.length>0&&(this.doFlushStash(this.stash,this.results),this.stash=[])}onPushOnStash(t){}shouldStash(t){throw new TypeError(" Do not call abstract method foo from child."+t)}doMatchesStash(t,e){throw new TypeError(" Do not call abstract method foo from child."+t+e)}doFlushStash(t,e){throw new TypeError(" Do not call abstract method foo from child."+t+e)}},N=class{footnoteLinks;footnotes;containLinks;formattedWords;constructor(t){this.footnoteLinks=t.footnoteLinks||[],this.footnotes=t.footnotes||[],this.containLinks=t.containLinks??!1,this.formattedWords=t.formattedWords??0}add(t){this.footnoteLinks=this.footnoteLinks.concat(t.footnoteLinks),this.footnotes=this.footnotes.concat(t.footnotes),this.containLinks=this.containLinks||t.containLinks,this.formattedWords+=t.formattedWords}};function D(t){t.sort((t,e)=>t.x-e.x)}var H={BOLD:{name:"BOLD",startSymbol:"<strong>",endSymbol:"</strong>"},OBLIQUE:{name:"OBLIQUE",startSymbol:"<em>",endSymbol:"</em>"},BOLD_OBLIQUE:{name:"BOLD_OBLIQUE",startSymbol:"<strong><em>",endSymbol:"</em></strong>"}},M={LINK:{name:"LINK",toText:t=>`<a href="${t}">${t}</a>`},FOOTNOTE_LINK:{name:"FOOTNOTE_LINK",attachWithoutWhitespace:!0,plainTextFormat:!0,toText:t=>`<sup><a href="#${t}">${t}</a></sup>`},FOOTNOTE:{name:"FOOTNOTE",toText:t=>`<p id="${t}">^${t}</p>`}},U=class{fontToFormats;constructor(t){this.fontToFormats=t}compact(t){D(t);const e=new B(this.fontToFormats);e.consumeAll(t.map(t=>new g({...t})));const s=e.complete();var n=0,o=0;return t.forEach(t=>{n=Math.max(n,t.height),o+=t.width}),new C({x:t[0].x,y:t[0].y,height:n,width:o,words:s,parsedElements:new N({footnoteLinks:e.footnoteLinks,footnotes:e.footnotes,containLinks:e.containLinks,formattedWords:e.formattedWords})})}},B=class extends F{fontToFormats;footnoteLinks;footnotes;formattedWords;containLinks;stashedNumber;firstY;currentItem;constructor(t){super(),this.fontToFormats=t,this.footnoteLinks=[],this.footnotes=[],this.formattedWords=0,this.containLinks=!1,this.stashedNumber=!1,this.currentItem=null}shouldStash(t){return this.firstY||(this.firstY=t.y),this.currentItem=t,!0}onPushOnStash(t){this.stashedNumber=n(t.text.trim())}doMatchesStash(t,e){if(this.fontToFormats.get(t.font)!==this.fontToFormats.get(e.font))return!1;const s=n(e.text.trim());return this.stashedNumber===s}doFlushStash(t,e){if(this.stashedNumber){const s=t.map(t=>t.text).join("").trim();t[0].y>this.firstY?(e.push(new k({string:`${s}`,type:M.FOOTNOTE_LINK})),this.footnoteLinks.push(parseInt(s))):this.currentItem&&this.currentItem.y<t[0].y?(e.push(new k({string:`${s}`,type:M.FOOTNOTE})),this.footnotes.push(s)):this.copyStashItemsAsText(t,e)}else this.copyStashItemsAsText(t,e)}copyStashItemsAsText(t,e){const s=this.fontToFormats.get(t[0].font);e.push(...this.itemsToWords(t,s))}itemsToWords(t,e){const s=(n=t,o="",r=null,n.forEach(t=>{var e=t.text;o.endsWith(" ")||e.startsWith(" ")||(r?t.x-r.x-r.width>5&&(o+=" "):a(t.text)&&(e+=" ")),o+=e,r=t}),o).split(" ");var n,o,r;const i=e?H[e]:null;return s.filter(t=>t.trim().length>0).map(t=>{var e=null;return t.startsWith("http:")?(this.containLinks=!0,e=M.LINK):t.startsWith("www.")&&(this.containLinks=!0,t=`http://${t}`,e=M.LINK),i&&this.formattedWords++,new k({string:t,type:e,format:i})})}};var A=class extends I{fontMap;constructor(t){super("Calculate Global Stats"),this.fontMap=t}transform(t){const e={},s={};var n,o=0;t.pages.forEach(t=>{t.items.forEach(t=>{t.height&&(e[t.height]=e[t.height]?e[t.height]+1:1,s[t.font]=s[t.font]?s[t.font]+1:1,t.height>o&&(o=t.height,n=t.font))})});const r=parseInt($(e)),a=$(s),i={};t.pages.forEach(t=>{var e;t.items.forEach(t=>{if(t.height===r&&t.text.trim().length>0){if(e&&t.y!==e.y){const s=e.y-t.y;s>0&&(i[s]=i[s]?i[s]+1:1)}e=t}else e=null})});const h=parseInt($(i)),l=[],c=/* @__PURE__ */new Map;this.fontMap?.forEach(function(t,e){l.push(e+" = "+t.name);const s=t.name.toLowerCase();var o=null;e===a?o=null:s.includes("bold")&&(s.includes("oblique")||s.includes("italic"))?o=H.BOLD_OBLIQUE:s.includes("bold")?o=H.BOLD:s.includes("oblique")||s.includes("italic")?o=H.OBLIQUE:s===n&&(o=H.BOLD),o&&c.set(e,o.name)}),l.sort();const m=t.pages.map(t=>({...t,items:t.items.map(t=>({...t}))}));return new S({...t,pages:m,globals:{mostUsedHeight:r,mostUsedFont:a,mostUsedDistance:h,maxHeight:o,maxHeightFont:n,fontToFormats:c},messages:["Items per height: "+JSON.stringify(e),"Items per font: "+JSON.stringify(s),"Items per distance: "+JSON.stringify(i),"Fonts:"+JSON.stringify(l)]})}};function $(t){var e=0,s="";return Object.keys(t).map(n=>{(!s||t[n]>e)&&(e=t[n],s=n)}),s}var P=class t extends x{constructor(e){if(super(e,C.name),this.constructor===t)throw new TypeError("Can not construct abstract class.")}completeTransform(t){return t.messages=[],t.pages.forEach(t=>{t.items=t.items.filter(t=>!t.annotation||t.annotation!==v),t.items.forEach(t=>t.annotation=null)}),t}},W=class{mostUsedDistance;constructor(t){this.mostUsedDistance=t.mostUsedDistance||12}group(t){const e=[];var s=[];return t.forEach(t=>{s.length>0&&Math.abs(s[0].y-t.y)>=this.mostUsedDistance/2&&(e.push(s),s=[]),s.push(t)}),e.push(s),e.forEach(t=>{D(t)}),e}},j={H1:{name:"H1",headline:!0,headlineLevel:1,toText:t=>"<h1>"+q(t.items,!0)+"</h1>"},H2:{name:"H2",headline:!0,headlineLevel:2,toText:t=>"<h2>"+q(t.items,!0)+"</h2>"},H3:{name:"H3",headline:!0,headlineLevel:3,toText:t=>"<h3>"+q(t.items,!0)+"</h3>"},H4:{name:"H4",headline:!0,headlineLevel:4,toText:t=>"<h4>"+q(t.items,!0)+"</h4>"},H5:{name:"H5",headline:!0,headlineLevel:5,toText:t=>"<h5>"+q(t.items,!0)+"</h5>"},H6:{name:"H6",headline:!0,headlineLevel:6,toText:t=>"<h6>"+q(t.items,!0)+"</h6>"},TOC:{name:"TOC",mergeToBlock:!0,toText:t=>q(t.items,!0)},FOOTNOTES:{name:"FOOTNOTES",mergeToBlock:!0,mergeFollowingNonTypedItems:!0,toText:t=>"<p>"+q(t.items,!1)+"</p>"},CODE:{name:"CODE",mergeToBlock:!0,toText:t=>"<code>"+q(t.items,!0)+"</code>"},LIST:{name:"LIST",mergeToBlock:!1,mergeFollowingNonTypedItemsWithSmallDistance:!0,toText:t=>"<ul>\n"+q(t.items,!1)+"</ul>"},PARAGRAPH:{name:"PARAGRAPH",toText:t=>"<p>"+q(t.items,!1)+"</p>"}};function q(t,e){var s,n="";const o=()=>{n+=s.endSymbol,s=null};return t.forEach((r,a)=>{var i;r&&(r.words.forEach((t,r)=>{const a=t.type,i=t.format;var h;!s||i&&i===s||o(),r>0&&(!a||!a.attachWithoutWhitespace)&&(1!==(h=t.string).length||"."!==h[0]&&"!"!==h[0]&&"?"!==h[0])&&(n+=" "),!i||s||e||(n+=(s=i).startSymbol),!a||e&&!a.plainTextFormat?n+=t.string:n+=a.toText(t.string)}),!s||a!==t.length-1&&(0===(i=t[a+1]).words.length?null:i.words[0].format)===s||o(),n+="\n")}),n}j.enumValueOf=function(t){return j[t]},j.isHeadline=function(t){return t&&2===t.name.length&&"H"===t.name[0]},j.blockToText=function(t){return t.type?t.type.toText(t):q(t.items,!1)},j.headlineByLevel=function(t){return 1===t?j.H1:2===t?j.H2:3===t?j.H3:4===t?j.H4:5===t?j.H5:(t>6&&console.warn("Unsupported headline level: "+t+" (supported are 1-6), defaulting to level 6"),j.H6)};var Y=class extends P{constructor(){super("Compact To Lines")}transform(t){const{mostUsedDistance:e,fontToFormats:s}=t.globals,n=[],o=[];var r=0,a=0;const i=new W({mostUsedDistance:e}),h=new U(s);return t.pages.forEach(t=>{if(t.items.length>0){const e=[];i.group(t.items).forEach(s=>{const i=h.compact(s);if(s.length>1&&(i.annotation=T,s.forEach(t=>{t.annotation=v,e.push(new C({...t}))})),0===i.words.length&&(i.annotation=v),e.push(i),i.parsedElements.formattedWords&&(a+=i.parsedElements.formattedWords),i.parsedElements.containLinks&&r++,i.parsedElements.footnoteLinks.length>0){const e=i.parsedElements.footnoteLinks.map(e=>({footnoteLink:e,page:t.index+1}));o.push.apply(o,e)}if(i.parsedElements.footnotes.length>0){i.type=j.FOOTNOTES;const e=i.parsedElements.footnotes.map(e=>({footnote:e,page:t.index+1}));n.push.apply(n,e)}}),t.items=e}}),new S({...t,messages:["Detected "+a+" formatted words","Found "+r+" links","Detected "+o.length+" footnotes links","Detected "+n.length+" footnotes"]})}};function R(t){var e=0;if(0===t.trim().length)return e;for(var n=0;n<t.length;n++){const o=t.charCodeAt(n);s(o)||32===o||160===o||(e=(e<<5)-e+o,e|=0)}return e}var V=class extends P{constructor(){super("Remove Repetitive Elements")}transform(t){const e=[],s={},n={};t.pages.forEach(t=>{const o=t.items.reduce((t,e)=>(e.y<t.minY?(t.minElements=[e],t.minY=e.y):e.y===t.minY&&t.minElements.push(e),e.y>t.maxY?(t.maxElements=[e],t.maxY=e.y):e.y===t.maxY&&t.maxElements.push(e),t),{minY:999,maxY:0,minElements:[],maxElements:[]}),r=R(o.minElements.reduce((t,e)=>t+e.text().toUpperCase(),"")),a=R(o.maxElements.reduce((t,e)=>t+e.text().toUpperCase(),""));e.push({minElements:o.minElements,maxElements:o.maxElements,minLineHash:r,maxLineHash:a}),s[r]=s[r]?s[r]+1:1,n[a]=n[a]?n[a]+1:1});var o=0,r=0;return t.pages.forEach((a,i)=>{s[e[i].minLineHash]>=Math.max(3,2*t.pages.length/3)&&(e[i].minElements.forEach(t=>{t.annotation=v}),r++),n[e[i].maxLineHash]>=Math.max(3,2*t.pages.length/3)&&(e[i].maxElements.forEach(t=>{t.annotation=v}),o++)}),new S({...t,messages:["Removed Header: "+o,"Removed Footers: "+r]})}},K=class extends P{constructor(){super("Vertical to Horizontal Text")}transform(t){var e=0;return t.pages.forEach(t=>{const s=new J;s.consumeAll(t.items),t.items=s.complete(),e+=s.foundVerticals}),new S({...t,messages:["Converted "+e+" verticals"]})}},J=class extends F{foundVerticals;constructor(){super(),this.foundVerticals=0}shouldStash(t){return 1===t.words.length&&1===t.words[0].string.length}doMatchesStash(t,e){return t.y-e.y>5&&t.words[0].type===e.words[0].type}doFlushStash(t,e){if(t.length>5){var s=[],n=999,o=0,r=0,a=0;t.forEach(t=>{t.annotation=v,e.push(t),s.push(t.words[0]),n=Math.min(n,t.x),o=Math.max(o,t.y),r+=t.width,a=Math.max(a,t.height)}),e.push(new C({...t[0],x:n,y:o,width:r,height:a,words:s,annotation:T})),this.foundVerticals++}else e.push(...t)}},Q=class{headlineCharCodes;stackedLineItems;stackedChars;constructor(t){this.headlineCharCodes=r(t.headline),this.stackedLineItems=[],this.stackedChars=0}consume(t){const e=r(t.text());if(this.matchAll(e)){if(this.stackedLineItems.push(t),this.stackedChars+=e.length,this.stackedChars===this.headlineCharCodes.length)return this.stackedLineItems}else this.stackedChars>0&&(this.stackedChars=0,this.stackedLineItems=[],this.consume(t));return null}matchAll(t){for(var e=0;e<t.length;e++){const s=this.headlineCharCodes[this.stackedChars+e];if(t[e]!==s)return!1}return!0}},_=class extends P{constructor(){super("Detect TOC")}transform(t){const e=[],r=Math.min(20,t.pages.length),a=new X;var i,h,c=[];t.pages.slice(0,r).forEach(t=>{var r=0;const l=/* @__PURE__ */new Set,m=[];var u,p;if(t.items.filter(t=>t.words.includes(t=>o(t.string,"."))).forEach(t=>{var e=t.words.filter(t=>!o(t.string,"."));const a=[];for(;e.length>0&&n(e[e.length-1].string);){const t=e.pop();a.unshift(t.string)}if(0===a.length&&e.length>0){const t=e[e.length-1];for(;s(t.string.charCodeAt(t.string.length-1));)a.unshift(t.string.charAt(t.string.length-1)),t.string=t.string.substring(0,t.string.length-1)}var i=a.length>0;i?(i=!0,u&&(e.push(...u),u=null),m.push(new Z({pageNumber:parseInt(a.join("")),lineItem:new C({...t,words:e})})),r++):h?(u&&l.add(p),u=e,p=t):h=t}),100*r/t.items.length>75){e.push(t.index+1),i=t,a.levelPageItems(m),c.push(...m);const s=[];t.items.forEach(t=>{l.has(t)||(t.annotation=v),s.push(t),t===h&&s.push(new C({...t,type:j.H2,annotation:T}))}),t.items=s}else h=null});var m=c.length;const u=[],p=[],f={};if(e.length>0){c.forEach(t=>{i.items.push(new C({words:[new k({string:" ".repeat(3*t.level)+"-"})].concat(t.lineItem.words),type:j.TOC,annotation:T}))});const e=function(t,e){for(var s of e){const e=z(t,s.lineItem.text());if(e)return e.index-s.pageNumber}return null}(t.pages.filter(t=>t.index>i.index),c);c.forEach(s=>{var n,o=t.pages[s.pageNumber+e];o&&((n=G(o,s.lineItem.text()))||(o=t.pages[s.pageNumber+e+1])&&(n=G(o,s.lineItem.text()))),n?function(t,e,s,n){s.headlineItems.forEach(t=>t.annotation=v);const o=j.headlineByLevel(e.level+2),r=s.headlineItems.reduce((t,e)=>Math.max(t,e.height),0);t.items.splice(s.lineIndex+1,0,new C({...s.headlineItems[0],words:e.lineItem.words,height:r,type:o,annotation:T}));var a=n[o.name];a?(a.min=Math.min(a.min,r),a.max=Math.max(a.max,r)):(a={min:r,max:r},n[o.name]=a)}(o,s,n,f):u.push(s)});var d=i.index+2,g=[];const s=e=>{g.length>0&&(g.forEach(s=>{const n=j.headlineByLevel(s.level+2),o=f[n.name];if(o){const[r,a]=function(t,e,s,n,o){const r=e.lineItem.text().toUpperCase();for(var a=n;a<=o;a++){const e=t[a-1];if(e){const t=e.items.findIndex(t=>!t.type&&!t.annotation&&t.height>=s.min&&t.height<=s.max&&l(r,t.text())>=.5);if(t>-1)return[a-1,t]}}return[-1,-1]}(t.pages,s,o,d,e);if(a>-1){const e=t.pages[r];e.items[a].annotation=v,e.items.splice(a+1,0,new C({...s.lineItem,type:n,annotation:T})),p.push(s)}}}),g=[])};u.length>0&&(c.forEach(t=>{u.includes(t)?g.push(t):(s(t.pageNumber),d=t.pageNumber)}),g.length>0&&s(t.pages.length))}const y=[];return y.push("Detected "+e.length+" table of content pages"),e.length>0&&(y.push("TOC headline heights: "+JSON.stringify(f)),y.push("Found TOC headlines: "+(m-u.length+p.length)+"/"+m)),u.length>0&&(y.push("Found TOC headlines (by size): "+p.map(t=>t.lineItem.text())),y.push("Missing TOC headlines: "+u.filter(t=>!p.includes(t)).map(t=>t.lineItem.text()+"=>"+t.pageNumber))),new S({...t,globals:{...t.globals,tocPages:e,headlineTypeToHeightRange:f},messages:y})}};function z(t,e){for(var s of t)if(G(s,e))return s;return null}function G(t,e){const s=new Q({headline:e});var n=0;for(var o of t.items){const t=s.consume(o);if(t)return{lineIndex:n,headlineItems:t};n++}return null}var X=class{levelByMethod;uniqueFonts;constructor(){this.levelByMethod=null,this.uniqueFonts=[]}levelPageItems(t){if(!this.levelByMethod)if(this.calculateUniqueX(t).length>1)this.levelByMethod=this.levelByXDiff;else{const e=this.calculateUniqueFonts(t);e.length>1?(this.uniqueFonts=e,this.levelByMethod=this.levelByFont):this.levelByMethod=this.levelToZero}this.levelByMethod(t)}levelByXDiff(t){const e=this.calculateUniqueX(t);t.forEach(t=>{t.level=e.indexOf(t.lineItem.x)})}levelByFont(t){t.forEach(t=>{t.level=this.uniqueFonts.indexOf(t.lineItem.font)})}levelToZero(t){t.forEach(t=>{t.level=0})}calculateUniqueX(t){var e=t.reduce(function(t,e){return t.indexOf(e.lineItem.x)<0&&t.push(e.lineItem.x),t},[]);return e.sort((t,e)=>t-e),e}calculateUniqueFonts(t){return t.reduce(function(t,e){return t.indexOf(e.lineItem.font)<0&&t.push(e.lineItem.font),t},[])}},Z=class{lineItem;pageNumber;level;constructor(t){this.lineItem=t.lineItem,this.pageNumber=t.pageNumber,this.level=0}},tt=class extends P{constructor(){super("Detect List Items")}transform(t){var e=0,s=0;return t.pages.forEach(t=>{const n=[];t.items.forEach(t=>{if(n.push(t),!t.type){var o=t.text();if(a(t.words[0].string))if(e++,"-"===t.words[0].string)t.annotation=L,t.type=j.LIST;else{t.annotation=v;const e=t.words.map(t=>new k({...t}));e[0].string="-",n.push(new C({...t,words:e,annotation:T,type:j.LIST}))}else/^[\s]*[\d]*[.][\s].*$/g.test(o)&&(s++,t.annotation=L,t.type=j.LIST)}}),t.items=n}),new S({...t,messages:["Detected "+e+" plain list items.","Detected "+s+" numbered list items."]})}},et=class extends P{constructor(){super("Detect Headers")}transform(t){const{tocPages:e,headlineTypeToHeightRange:s,mostUsedHeight:n,mostUsedDistance:o,mostUsedFont:r,maxHeight:a}=t.globals,h=e.length>0;var l=0;const c=function(t,e){const s=/* @__PURE__ */new Set;return t.forEach(t=>{t.items.forEach(n=>{n.type||n.height!==e||s.add(t)})}),s}(t.pages,a),m=n+(a-n)/4;if(c.forEach(t=>{t.items.forEach(t=>{const e=t.height;!t.type&&e>m&&(t.type=e===a?j.H1:j.H2,t.annotation=L,l++)})}),h)Object.keys(s).forEach(e=>{var o=s[e];o.max>n&&t.pages.forEach(t=>{t.items.forEach(t=>{t.type||t.height!==o.max||(t.annotation=L,t.type=j.enumValueOf(e),l++)})})});else{const e=[];t.pages.forEach(t=>{t.items.forEach(t=>{!t.type&&t.height>n&&!i(t.text())&&(e.includes(t.height)||e.push(t.height))})}),e.sort((t,e)=>e-t),e.forEach((e,s)=>{if(s+2<=6){const n=j.headlineByLevel(2+s);t.pages.forEach(t=>{t.items.forEach(t=>{t.type||t.height!==e||i(t.text())||(l++,t.annotation=L,t.type=n)})})}})}var u=1;if(t.pages.forEach(t=>{t.items.forEach(t=>{t.type&&t.type.headline&&(u=Math.max(u,t.type.headlineLevel))})}),u<6){const e=j.headlineByLevel(u+1);t.pages.forEach(t=>{var s;t.items.forEach(t=>{!t.type&&t.height===n&&t.font!==r&&(!s||s.y<t.y||s.type&&s.type.headline||s.y-t.y>2*o)&&t.text()===t.text().toUpperCase()&&(l++,t.annotation=L,t.type=e),s=t})})}return new S({...t,messages:["Detected "+l+" headlines."]})}};var st=class extends d{items;constructor(t){super(t),this.items=[],t.items&&t.items.forEach(t=>this.addItem(t))}addItem(t){if(this.type&&t.type&&this.type!==t.type)throw new Error(`Adding item of type ${t.type.name} to block of type ${this.type.name}`);this.type||(this.type=t.type),t.parsedElements&&(this.parsedElements?this.parsedElements.add(t.parsedElements):this.parsedElements=t.parsedElements);const e=new C({...t});e.type=null,this.items.push(e)}},nt=class t extends x{constructor(e){if(super(e,st.name),this.constructor===t)throw new TypeError("Can not construct abstract class.")}completeTransform(t){return t.messages=[],t.pages.forEach(t=>{t.items=t.items.filter(t=>!t.annotation||t.annotation!==v),t.items.forEach(t=>t.annotation=null)}),t}},ot=class extends nt{constructor(){super("Gather Blocks")}transform(t){const{mostUsedDistance:e}=t.globals;var s=0,n=0;return t.pages.map(t=>{n+=t.items.length;const o=[];var r=new st({});const a=()=>{r.items.length>1&&(r.annotation=L),o.push(r),r=new st({}),s++};var i=function(t){var e=999;return t.forEach(t=>{e=Math.min(e,t.x)}),999===e?null:e}(t.items);t.items.forEach(t=>{r.items.length>0&&function(t,e,s,n){if(t.type&&t.type.mergeFollowingNonTypedItems&&!e.type)return!1;const o=t.items[t.items.length-1],r=function(t,e,s,n){const o=t.y-e.y;if(o<0-n/2)return!0;var r=n+1;t.x>s&&e.x>s&&(r=n+n/2);return o>r}(o,e,s,n);if(t.type&&t.type.mergeFollowingNonTypedItemsWithSmallDistance&&!e.type&&!r)return!1;if(e.type!==t.type)return!0;return e.type?!e.type.mergeToBlock:r}(r,t,i,e)&&a(),r.addItem(t)}),r.items.length>0&&a(),t.items=o}),new S({...t,messages:["Gathered "+s+" blocks out of "+n+" line items"]})}};var rt=class extends nt{constructor(){super("$1")}transform(t){const e=t.globals.mostUsedHeight??0;var s=0;return t.pages.forEach(t=>{var n=function(t){var e=999;return t.forEach(t=>{t.items.forEach(t=>{e=Math.min(e,t.x)})}),999===e?null:e}(t.items);t.items.forEach(t=>{!t.type&&function(t,e,s){if(0===e.length)return!1;if(1===e.length)return e[0].x>t&&e[0].height<=s+1;for(var n of e)if(n.x===t)return!1;return!0}(n,t.items,e)&&(t.annotation=L,t.type=j.CODE,s++)})}),new S({...t,messages:["Detected "+s+" code/quote items."]})}};var at,it=class extends nt{constructor(){super("Level Lists")}transform(t){var e=0,s=0;return t.pages.forEach(t=>{t.items.filter(t=>t.type===j.LIST).forEach(t=>{var n,o=0;const r={};var a=!1;t.items.forEach(t=>{n?t.x>n?(o++,r[t.x]=o):t.x<n&&(o=r[t.x]):r[t.x]=0,o>0&&(t.words=[new k({string:" ".repeat(3*o)})].concat(t.words),a=!0),n=t.x}),e++,a?(s++,t.annotation=O):t.annotation=b})}),new S({...t,messages:["Modified "+s+" / "+e+" list blocks."]})}},ht=class extends x{constructor(){super("To Text Blocks","TextBlock")}transform(t){return t.pages.forEach(t=>{const e=[];t.items.forEach(t=>{const s=t.type?t.type.name:"Unknown";e.push({category:s,text:j.blockToText(t)})}),t.items=e}),new S({...t})}},lt=class extends x{constructor(){super("To HTML","String")}transform(t){return t.pages.forEach(t=>{var e="";t.items.forEach(t=>{let s;s="TOC"===t.category?t.text:t.text.replace(/(\r\n|\n|\r)/gm,"\n"),"LIST"!==t.category&&(s=s.split("- ").join("")),"CODE"===t.category&&(s=s.split("<code>").join("").split("</code>").join("")),e+=`<p>${s}</p>\n\n`}),t.items=[e]}),new S({...t})}};async function ct(t,e={}){const{addPageNumbers:s=!1,addCitation:n=!0,liteParseOptions:o={}}=e,r="string"==typeof t?await w(t,{responseType:"arraybuffer",timeout:10}):t;let a;try{({LiteParse:a}=await import("@llamaindex/liteparse"))}catch(p){return{error:`method: 'liteparse' requires the optional @llamaindex/liteparse dependency (Node.js only): ${p.message}`}}const i=new a({quiet:!0,ocrEnabled:!1,ocrFailureFatal:!1,...o});let l;try{l=await i.parse(new Uint8Array(r))}catch(p){return{error:p.message}}const c=l.pages.reduce((t,e)=>{const n=e.text.split(/\n{2,}/).filter(t=>t.trim().length>0).map(t=>h(t).replace(/\n/g,"<br/>")).join("</p><p>");return t+`<p id="page-${e.pageNum}">${s?` [${e.pageNum}] `:""}${n}</p>`},"");let m,u;return n&&(u=l.creator||l.producer,m=l.pages[0]?.text.split("\n").find(t=>t.trim().length>0)),{author:u,title:m,html:c,format:"pdf"}}async function mt(t,e={}){const{addPageNumbers:s=!1,addCitation:n=!0,liteParseOptions:o={}}=e,r="string"==typeof t?await w(t,{responseType:"arraybuffer",timeout:10}):t;let a;try{a=await import("@llamaindex/liteparse-wasm"),await async function(t){at||(at=t.default()),await at}(a)}catch(p){return{error:`method: 'liteparse-wasm' requires the optional @llamaindex/liteparse-wasm dependency: ${p.message}`}}const i=new a.LiteParse({quiet:!0,ocrEnabled:!1,ocrFailureFatal:!1,...o});let l;try{l=await i.parse(new Uint8Array(r))}catch(p){return{error:p.message}}const c=l.pages.reduce((t,e)=>{const n=e.text.split(/\n{2,}/).filter(t=>t.trim().length>0).map(t=>h(t).replace(/\n/g,"<br/>")).join("</p><p>");return t+`<p id="page-${e.pageNum}">${s?` [${e.pageNum}] `:""}${n}</p>`},"");let m,u;return n&&(u=l.creator||l.producer,m=l.pages[0]?.text.split("\n").find(t=>t.trim().length>0)),{author:u,title:m,html:c,format:"pdf"}}async function ut(t,e={}){const s="string"==typeof t?await w(t,{responseType:"arraybuffer",timeout:10}):t,{LiteParse:n}=await import("@llamaindex/liteparse"),o=await new n({quiet:!0,...e.liteParseOptions}).isComplex(new Uint8Array(s));return{needsOcr:o.some(t=>t.needsOcr),pages:o,reasons:[...new Set(o.flatMap(t=>t.reasons))]}}async function pt(t,e={}){if("liteparse"===e.method){const{method:s,...n}=e;return ct(t,n)}if("liteparse-wasm"===e.method){const{method:s,...n}=e;return mt(t,n)}var{addPageNumbers:s=!1,addCitation:n=!0}=e,o="string"==typeof t?await w(t,{responseType:"arraybuffer",timeout:10}):t;let r;try{let{resolvePDFJS:t}=await import("https://cdn.jsdelivr.net/npm/pdfjs-serverless@1.1.0/+esm");const{getDocument:e}=await t();r=await e({data:new Uint8Array(o),useSystemFonts:!0,verbosity:0}).promise}catch(T){return{error:T.message}}const a=[...Array(r.numPages).keys()].map(t=>new y({index:t}));let i,h={};for(let f=1;f<=r.numPages;f++){const t=await r.getPage(f),e=await t.getTextContent();if(!(Object.keys(h).length<10)){i=p(h);break}h=u(h,t.pageNumber-1,e.items)}let l=i?i.pageNum:0;for(let u=1;u<=r.numPages;u++){const t=await r.getPage(u);await t.getOperatorList();const e=t.getViewport({scale:1});let s=await t.getTextContent();i&&t.pageIndex>=i.pageIndex&&(s=f(s,l),l++);const n=s.items.map(t=>{const s=[1,0,0,1,0,0];for(let r=0;r<6;r++)s[r]+=t.transform[r]*e.transform[r%2?3:0],r%2&&(s[r+1]+=t.transform[r]*e.transform[1]);const n=Math.sqrt(s[2]*s[2]+s[3]*s[3]),o=t.height/n;return new g({x:Math.round(t.transform[4]),y:Math.round(t.transform[5]),width:Math.round(t.width),height:Math.round(o<=1?t.height:o),text:t.str,font:t.fontName})});a[t.pageNumber-1].items=n}var c=new S({pages:a});let m;[new A,new Y,new V,new K,new _,new et,new tt,new ot,new rt,new it,new ht,new lt].forEach(t=>{m&&(c=m.completeTransform(c)),c=t.transform(c),m=t});var d=c.pages.reduce((t,e,n)=>t+`<p id="page-${n+1}">${s?` [${n+1}] `:""}${e.items.join('</p><p id="page-'+n+'">')}</p>`,"");if(n){var{Author:x,Title:E}=(await r.getMetadata()).info;E=d.slice(0,400).match(/<h[0-9]>(.*?)<\/h[0-9]>/)?.[1]||E}return{author:x,title:E,html:d,format:"pdf"}}export{pt as convertPDFToHTML,ct as convertPDFToHTMLWithLiteParse,mt as convertPDFToHTMLWithLiteParseWasm,ut as detectPdfNeedsOcr};
1
+ function t(t){for(;32===t.charCodeAt(0);)t=t.substring(1,t.length);return t}function e(t){for(;32===t.charCodeAt(t.length-1);)t=t.substring(0,t.length-1);return t}function s(t){return t>=48&&t<=57}function n(t){for(var e=0;e<t.length;e++)if(!s(t.charCodeAt(e)))return!1;return!0}function r(t,e){const s=e.charCodeAt(0);for(var n=0;n<t.length;n++)if(t.charCodeAt(n)!==s)return!1;return!0}function o(t){return function(t){const e=[];for(var s=0;s<t.length;s++)e.push(t.charCodeAt(s));return e}(t=t.toUpperCase()).filter(t=>32!==t&&9!==t&&46!==t)}function a(t){if(t.length>1)return!1;const e=t.charAt(0);return"-"===e||"•"===e||"–"===e}function i(t){return/^[\s]*[-•–][\s].*$/g.test(t)}function c(t){return t.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function l(t,e){const s=new Set(t.toUpperCase().split(" ")),n=new Set(e.toUpperCase().split(" "));return new Set([...s].filter(t=>n.has(t))).size/Math.max(s.size,n.size)}var h=(t,e,s)=>Math.floor(t/e*s),m=(s,r,o)=>{for(const{str:a}of s){const s=e(t(a));n(s)&&(r[o]||(r[o]=[]),r[o].push(Number(s)))}return r},u=(t,e,s)=>{const n=h(1,6,s.length),r=h(5,6,s.length),o=m(s.slice(0,n),t,e);return m(s.slice(r),o,e)},p=t=>{let e=0;const s=Object.keys(t);if(0!==s.length&&1!==s.length)for(let n=0;n<s.length-1;n++){const r=t[s[n]],o=t[s[n+1]],a=e;for(let t=0;t<r.length&&e<2;t++)for(let a=0;a<o.length&&e<2;a++){const i=Number(s[n+1])-Number(s[n]);(r[t]+1===o[a]||i>1&&r[t]+i===o[a])&&e++}let i=n>0?Object.entries(t)[n-1]:Object.entries(t)[n];if(a===e)e=0,i=Object.entries(t)[n];else if(e>=2)return{pageIndex:Number(i[0]),pageNum:i[1][0]}}},d=(t,e)=>{const s={items:[...t.items]},n=h(1,6,s.items.length),r=h(5,6,s.items.length);return s.items=s.items.filter((t,o)=>{const a=o>0&&o<n,i=o>r&&o<s.items.length;return a||i?Number(t.str)!==Number(e):t}),s},f=class t{type;annotation;parsedElements;constructor(e){if(this.constructor===t)throw new TypeError("Can not construct abstract class.");this.type=e.type??null,this.annotation=e.annotation??null,this.parsedElements=e.parsedElements??null}},g=class extends f{x;y;width;height;text;font;lineFormat;unopenedFormat;unclosedFormat;constructor(t){super(t),this.x=t.x,this.y=t.y,this.width=t.width,this.height=t.height,this.text=t.text,this.font=t.font,this.lineFormat=t.lineFormat??null,this.unopenedFormat=t.unopenedFormat??null,this.unclosedFormat=t.unclosedFormat??null}},y=class{index;items;constructor(t){this.index=t.index,this.items=t.items||[]}};async function w(t,e={}){const s=e.timeout?1e3*e.timeout:1e4,n=new AbortController,r=setTimeout(()=>n.abort(),s);try{const s=await fetch(t,{signal:n.signal});if(clearTimeout(r),!s.ok)throw new Error(`HTTP ${s.status}`);return"arraybuffer"===e.responseType?await s.arrayBuffer():await s.text()}catch(o){throw clearTimeout(r),o}}var x=class t{name;itemType;constructor(e,s){if(this.constructor===t)throw new TypeError("Can not construct abstract class.");if(this.transform===t.prototype.transform)throw new TypeError("Please implement abstract method 'transform()'.");this.name=e,this.itemType=s}transform(t){throw new TypeError("Do not call abstract method foo from child.")}completeTransform(t){return t.messages=[],t}},v=class{category;color;constructor(t){this.category=t.category,this.color=t.color}},E=new v({category:"Added",color:"green"}),T=new v({category:"Removed",color:"red"}),b=new v({category:"Unchanged",color:"brown"}),O=new v({category:"Detected",color:"green"}),S=new v({category:"Modified",color:"green"}),L=class t extends x{constructor(e){if(super(e,g.name),this.constructor===t)throw new TypeError("Can not construct abstract class.")}completeTransform(t){return t.messages=[],t.pages.forEach(t=>{t.items=t.items.filter(t=>!t.annotation||t.annotation!==T),t.items.forEach(t=>t.annotation=null)}),t}},I=class{pages;globals;messages;constructor(t){this.pages=t.pages||[],this.globals=t.globals||{},this.messages=t.messages||[]}},C=class{string;type;format;constructor(t){this.string=t.string,this.type=t.type??null,this.format=t.format??null}},k=class extends f{x;y;width;height;words;constructor(t){super(t),this.x=t.x??0,this.y=t.y??0,this.width=t.width??0,this.height=t.height??0,this.words=t.words||[],t.text&&!t.words&&(this.words=t.text.split(" ").filter(t=>t.trim().length>0).map(t=>new C({string:t})))}text(){return this.wordStrings().join(" ")}wordStrings(){return this.words.map(t=>t.string)}},N=class t{results;stash;constructor(){if(this.constructor===t)throw new TypeError("Can not construct abstract class.");this.results=[],this.stash=[]}consumeAll(t){t.forEach(t=>this.consume(t))}consume(t){this.shouldStash(t)?(this.matchesStash(t)||this.flushStash(),this.pushOnStash(t)):(this.stash.length>0&&this.flushStash(),this.results.push(t))}pushOnStash(t){this.onPushOnStash(t),this.stash.push(t)}complete(){return this.stash.length>0&&this.flushStash(),this.results}matchesStash(t){if(0===this.stash.length)return!0;const e=this.stash[this.stash.length-1];return this.doMatchesStash(e,t)}flushStash(){this.stash.length>0&&(this.doFlushStash(this.stash,this.results),this.stash=[])}onPushOnStash(t){}shouldStash(t){throw new TypeError(" Do not call abstract method foo from child."+t)}doMatchesStash(t,e){throw new TypeError(" Do not call abstract method foo from child."+t+e)}doFlushStash(t,e){throw new TypeError(" Do not call abstract method foo from child."+t+e)}},F=class{footnoteLinks;footnotes;containLinks;formattedWords;constructor(t){this.footnoteLinks=t.footnoteLinks||[],this.footnotes=t.footnotes||[],this.containLinks=t.containLinks??!1,this.formattedWords=t.formattedWords??0}add(t){this.footnoteLinks=this.footnoteLinks.concat(t.footnoteLinks),this.footnotes=this.footnotes.concat(t.footnotes),this.containLinks=this.containLinks||t.containLinks,this.formattedWords+=t.formattedWords}};function _(t){t.sort((t,e)=>t.x-e.x)}var $={BOLD:{name:"BOLD",startSymbol:"<strong>",endSymbol:"</strong>"},OBLIQUE:{name:"OBLIQUE",startSymbol:"<em>",endSymbol:"</em>"},BOLD_OBLIQUE:{name:"BOLD_OBLIQUE",startSymbol:"<strong><em>",endSymbol:"</em></strong>"}},B={LINK:{name:"LINK",toText:t=>`<a href="${t}">${t}</a>`},FOOTNOTE_LINK:{name:"FOOTNOTE_LINK",attachWithoutWhitespace:!0,plainTextFormat:!0,toText:t=>`<sup><a href="#${t}">${t}</a></sup>`},FOOTNOTE:{name:"FOOTNOTE",toText:t=>`<p id="${t}">^${t}</p>`}},M=class{fontToFormats;constructor(t){this.fontToFormats=t}compact(t){_(t);const e=new D(this.fontToFormats);e.consumeAll(t.map(t=>new g({...t})));const s=e.complete();var n=0,r=0;return t.forEach(t=>{n=Math.max(n,t.height),r+=t.width}),new k({x:t[0].x,y:t[0].y,height:n,width:r,words:s,parsedElements:new F({footnoteLinks:e.footnoteLinks,footnotes:e.footnotes,containLinks:e.containLinks,formattedWords:e.formattedWords})})}},D=class extends N{fontToFormats;footnoteLinks;footnotes;formattedWords;containLinks;stashedNumber;firstY;currentItem;constructor(t){super(),this.fontToFormats=t,this.footnoteLinks=[],this.footnotes=[],this.formattedWords=0,this.containLinks=!1,this.stashedNumber=!1,this.currentItem=null}shouldStash(t){return this.firstY||(this.firstY=t.y),this.currentItem=t,!0}onPushOnStash(t){this.stashedNumber=n(t.text.trim())}doMatchesStash(t,e){if(this.fontToFormats.get(t.font)!==this.fontToFormats.get(e.font))return!1;const s=n(e.text.trim());return this.stashedNumber===s}doFlushStash(t,e){if(this.stashedNumber){const s=t.map(t=>t.text).join("").trim();t[0].y>this.firstY?(e.push(new C({string:`${s}`,type:B.FOOTNOTE_LINK})),this.footnoteLinks.push(parseInt(s))):this.currentItem&&this.currentItem.y<t[0].y?(e.push(new C({string:`${s}`,type:B.FOOTNOTE})),this.footnotes.push(s)):this.copyStashItemsAsText(t,e)}else this.copyStashItemsAsText(t,e)}copyStashItemsAsText(t,e){const s=this.fontToFormats.get(t[0].font);e.push(...this.itemsToWords(t,s))}itemsToWords(t,e){const s=(n=t,r="",o=null,n.forEach(t=>{var e=t.text;r.endsWith(" ")||e.startsWith(" ")||(o?t.x-o.x-o.width>5&&(r+=" "):a(t.text)&&(e+=" ")),r+=e,o=t}),r).split(" ");var n,r,o;const i=e?$[e]:null;return s.filter(t=>t.trim().length>0).map(t=>{var e=null;return t.startsWith("http:")?(this.containLinks=!0,e=B.LINK):t.startsWith("www.")&&(this.containLinks=!0,t=`http://${t}`,e=B.LINK),i&&this.formattedWords++,new C({string:t,type:e,format:i})})}};var U=class extends L{fontMap;constructor(t){super("Calculate Global Stats"),this.fontMap=t}transform(t){const e={},s={};var n,r=0;t.pages.forEach(t=>{t.items.forEach(t=>{t.height&&(e[t.height]=e[t.height]?e[t.height]+1:1,s[t.font]=s[t.font]?s[t.font]+1:1,t.height>r&&(r=t.height,n=t.font))})});const o=parseInt(H(e)),a=H(s),i={};t.pages.forEach(t=>{var e;t.items.forEach(t=>{if(t.height===o&&t.text.trim().length>0){if(e&&t.y!==e.y){const s=e.y-t.y;s>0&&(i[s]=i[s]?i[s]+1:1)}e=t}else e=null})});const c=parseInt(H(i)),l=[],h=/* @__PURE__ */new Map;this.fontMap?.forEach(function(t,e){l.push(e+" = "+t.name);const s=t.name.toLowerCase();var r=null;e===a?r=null:s.includes("bold")&&(s.includes("oblique")||s.includes("italic"))?r=$.BOLD_OBLIQUE:s.includes("bold")?r=$.BOLD:s.includes("oblique")||s.includes("italic")?r=$.OBLIQUE:s===n&&(r=$.BOLD),r&&h.set(e,r.name)}),l.sort();const m=t.pages.map(t=>({...t,items:t.items.map(t=>({...t}))}));return new I({...t,pages:m,globals:{mostUsedHeight:o,mostUsedFont:a,mostUsedDistance:c,maxHeight:r,maxHeightFont:n,fontToFormats:h},messages:["Items per height: "+JSON.stringify(e),"Items per font: "+JSON.stringify(s),"Items per distance: "+JSON.stringify(i),"Fonts:"+JSON.stringify(l)]})}};function H(t){var e=0,s="";return Object.keys(t).map(n=>{(!s||t[n]>e)&&(e=t[n],s=n)}),s}var A=class t extends x{constructor(e){if(super(e,k.name),this.constructor===t)throw new TypeError("Can not construct abstract class.")}completeTransform(t){return t.messages=[],t.pages.forEach(t=>{t.items=t.items.filter(t=>!t.annotation||t.annotation!==T),t.items.forEach(t=>t.annotation=null)}),t}},P=class{mostUsedDistance;constructor(t){this.mostUsedDistance=t.mostUsedDistance||12}group(t){const e=[];var s=[];return t.forEach(t=>{s.length>0&&Math.abs(s[0].y-t.y)>=this.mostUsedDistance/2&&(e.push(s),s=[]),s.push(t)}),e.push(s),e.forEach(t=>{_(t)}),e}},j={H1:{name:"H1",headline:!0,headlineLevel:1,toText:t=>"<h1>"+W(t.items,!0)+"</h1>"},H2:{name:"H2",headline:!0,headlineLevel:2,toText:t=>"<h2>"+W(t.items,!0)+"</h2>"},H3:{name:"H3",headline:!0,headlineLevel:3,toText:t=>"<h3>"+W(t.items,!0)+"</h3>"},H4:{name:"H4",headline:!0,headlineLevel:4,toText:t=>"<h4>"+W(t.items,!0)+"</h4>"},H5:{name:"H5",headline:!0,headlineLevel:5,toText:t=>"<h5>"+W(t.items,!0)+"</h5>"},H6:{name:"H6",headline:!0,headlineLevel:6,toText:t=>"<h6>"+W(t.items,!0)+"</h6>"},TOC:{name:"TOC",mergeToBlock:!0,toText:t=>W(t.items,!0)},FOOTNOTES:{name:"FOOTNOTES",mergeToBlock:!0,mergeFollowingNonTypedItems:!0,toText:t=>"<p>"+W(t.items,!1)+"</p>"},CODE:{name:"CODE",mergeToBlock:!0,toText:t=>"<code>"+W(t.items,!0)+"</code>"},LIST:{name:"LIST",mergeToBlock:!1,mergeFollowingNonTypedItemsWithSmallDistance:!0,toText:t=>"<ul>\n"+W(t.items,!1)+"</ul>"},PARAGRAPH:{name:"PARAGRAPH",toText:t=>"<p>"+W(t.items,!1)+"</p>"}};function W(t,e){var s,n="";const r=()=>{n+=s.endSymbol,s=null};return t.forEach((o,a)=>{var i;o&&(o.words.forEach((t,o)=>{const a=t.type,i=t.format;var c;!s||i&&i===s||r(),o>0&&(!a||!a.attachWithoutWhitespace)&&(1!==(c=t.string).length||"."!==c[0]&&"!"!==c[0]&&"?"!==c[0])&&(n+=" "),!i||s||e||(n+=(s=i).startSymbol),!a||e&&!a.plainTextFormat?n+=t.string:n+=a.toText(t.string)}),!s||a!==t.length-1&&(0===(i=t[a+1]).words.length?null:i.words[0].format)===s||r(),n+="\n")}),n}j.enumValueOf=function(t){return j[t]},j.isHeadline=function(t){return t&&2===t.name.length&&"H"===t.name[0]},j.blockToText=function(t){return t.type?t.type.toText(t):W(t.items,!1)},j.headlineByLevel=function(t){return 1===t?j.H1:2===t?j.H2:3===t?j.H3:4===t?j.H4:5===t?j.H5:(t>6&&console.warn("Unsupported headline level: "+t+" (supported are 1-6), defaulting to level 6"),j.H6)};var q=class extends A{constructor(){super("Compact To Lines")}transform(t){const{mostUsedDistance:e,fontToFormats:s}=t.globals,n=[],r=[];var o=0,a=0;const i=new P({mostUsedDistance:e}),c=new M(s);return t.pages.forEach(t=>{if(t.items.length>0){const e=[];i.group(t.items).forEach(s=>{const i=c.compact(s);if(s.length>1&&(i.annotation=E,s.forEach(t=>{t.annotation=T,e.push(new k({...t}))})),0===i.words.length&&(i.annotation=T),e.push(i),i.parsedElements.formattedWords&&(a+=i.parsedElements.formattedWords),i.parsedElements.containLinks&&o++,i.parsedElements.footnoteLinks.length>0){const e=i.parsedElements.footnoteLinks.map(e=>({footnoteLink:e,page:t.index+1}));r.push.apply(r,e)}if(i.parsedElements.footnotes.length>0){i.type=j.FOOTNOTES;const e=i.parsedElements.footnotes.map(e=>({footnote:e,page:t.index+1}));n.push.apply(n,e)}}),t.items=e}}),new I({...t,messages:["Detected "+a+" formatted words","Found "+o+" links","Detected "+r.length+" footnotes links","Detected "+n.length+" footnotes"]})}};function R(t){var e=0;if(0===t.trim().length)return e;for(var n=0;n<t.length;n++){const r=t.charCodeAt(n);s(r)||32===r||160===r||(e=(e<<5)-e+r,e|=0)}return e}var Y=class extends A{constructor(){super("Remove Repetitive Elements")}transform(t){const e=[],s={},n={};t.pages.forEach(t=>{const r=t.items.reduce((t,e)=>(e.y<t.minY?(t.minElements=[e],t.minY=e.y):e.y===t.minY&&t.minElements.push(e),e.y>t.maxY?(t.maxElements=[e],t.maxY=e.y):e.y===t.maxY&&t.maxElements.push(e),t),{minY:999,maxY:0,minElements:[],maxElements:[]}),o=R(r.minElements.reduce((t,e)=>t+e.text().toUpperCase(),"")),a=R(r.maxElements.reduce((t,e)=>t+e.text().toUpperCase(),""));e.push({minElements:r.minElements,maxElements:r.maxElements,minLineHash:o,maxLineHash:a}),s[o]=s[o]?s[o]+1:1,n[a]=n[a]?n[a]+1:1});var r=0,o=0;return t.pages.forEach((a,i)=>{s[e[i].minLineHash]>=Math.max(3,2*t.pages.length/3)&&(e[i].minElements.forEach(t=>{t.annotation=T}),o++),n[e[i].maxLineHash]>=Math.max(3,2*t.pages.length/3)&&(e[i].maxElements.forEach(t=>{t.annotation=T}),r++)}),new I({...t,messages:["Removed Header: "+r,"Removed Footers: "+o]})}},V=class extends A{constructor(){super("Vertical to Horizontal Text")}transform(t){var e=0;return t.pages.forEach(t=>{const s=new z;s.consumeAll(t.items),t.items=s.complete(),e+=s.foundVerticals}),new I({...t,messages:["Converted "+e+" verticals"]})}},z=class extends N{foundVerticals;constructor(){super(),this.foundVerticals=0}shouldStash(t){return 1===t.words.length&&1===t.words[0].string.length}doMatchesStash(t,e){return t.y-e.y>5&&t.words[0].type===e.words[0].type}doFlushStash(t,e){if(t.length>5){var s=[],n=999,r=0,o=0,a=0;t.forEach(t=>{t.annotation=T,e.push(t),s.push(t.words[0]),n=Math.min(n,t.x),r=Math.max(r,t.y),o+=t.width,a=Math.max(a,t.height)}),e.push(new k({...t[0],x:n,y:r,width:o,height:a,words:s,annotation:E})),this.foundVerticals++}else e.push(...t)}},J=class{headlineCharCodes;stackedLineItems;stackedChars;constructor(t){this.headlineCharCodes=o(t.headline),this.stackedLineItems=[],this.stackedChars=0}consume(t){const e=o(t.text());if(this.matchAll(e)){if(this.stackedLineItems.push(t),this.stackedChars+=e.length,this.stackedChars===this.headlineCharCodes.length)return this.stackedLineItems}else this.stackedChars>0&&(this.stackedChars=0,this.stackedLineItems=[],this.consume(t));return null}matchAll(t){for(var e=0;e<t.length;e++){const s=this.headlineCharCodes[this.stackedChars+e];if(t[e]!==s)return!1}return!0}},K=class extends A{constructor(){super("Detect TOC")}transform(t){const e=[],o=Math.min(20,t.pages.length),a=new G;var i,c,h=[];t.pages.slice(0,o).forEach(t=>{var o=0;const l=/* @__PURE__ */new Set,m=[];var u,p;if(t.items.filter(t=>t.words.includes(t=>r(t.string,"."))).forEach(t=>{var e=t.words.filter(t=>!r(t.string,"."));const a=[];for(;e.length>0&&n(e[e.length-1].string);){const t=e.pop();a.unshift(t.string)}if(0===a.length&&e.length>0){const t=e[e.length-1];for(;s(t.string.charCodeAt(t.string.length-1));)a.unshift(t.string.charAt(t.string.length-1)),t.string=t.string.substring(0,t.string.length-1)}var i=a.length>0;i?(i=!0,u&&(e.push(...u),u=null),m.push(new Z({pageNumber:parseInt(a.join("")),lineItem:new k({...t,words:e})})),o++):c?(u&&l.add(p),u=e,p=t):c=t}),100*o/t.items.length>75){e.push(t.index+1),i=t,a.levelPageItems(m),h.push(...m);const s=[];t.items.forEach(t=>{l.has(t)||(t.annotation=T),s.push(t),t===c&&s.push(new k({...t,type:j.H2,annotation:E}))}),t.items=s}else c=null});var m=h.length;const u=[],p=[],d={};if(e.length>0){h.forEach(t=>{i.items.push(new k({words:[new C({string:" ".repeat(3*t.level)+"-"})].concat(t.lineItem.words),type:j.TOC,annotation:E}))});const e=function(t,e){for(var s of e){const e=Q(t,s.lineItem.text());if(e)return e.index-s.pageNumber}return null}(t.pages.filter(t=>t.index>i.index),h);h.forEach(s=>{var n,r=t.pages[s.pageNumber+e];r&&((n=X(r,s.lineItem.text()))||(r=t.pages[s.pageNumber+e+1])&&(n=X(r,s.lineItem.text()))),n?function(t,e,s,n){s.headlineItems.forEach(t=>t.annotation=T);const r=j.headlineByLevel(e.level+2),o=s.headlineItems.reduce((t,e)=>Math.max(t,e.height),0);t.items.splice(s.lineIndex+1,0,new k({...s.headlineItems[0],words:e.lineItem.words,height:o,type:r,annotation:E}));var a=n[r.name];a?(a.min=Math.min(a.min,o),a.max=Math.max(a.max,o)):(a={min:o,max:o},n[r.name]=a)}(r,s,n,d):u.push(s)});var f=i.index+2,g=[];const s=e=>{g.length>0&&(g.forEach(s=>{const n=j.headlineByLevel(s.level+2),r=d[n.name];if(r){const[o,a]=function(t,e,s,n,r){const o=e.lineItem.text().toUpperCase();for(var a=n;a<=r;a++){const e=t[a-1];if(e){const t=e.items.findIndex(t=>!t.type&&!t.annotation&&t.height>=s.min&&t.height<=s.max&&l(o,t.text())>=.5);if(t>-1)return[a-1,t]}}return[-1,-1]}(t.pages,s,r,f,e);if(a>-1){const e=t.pages[o];e.items[a].annotation=T,e.items.splice(a+1,0,new k({...s.lineItem,type:n,annotation:E})),p.push(s)}}}),g=[])};u.length>0&&(h.forEach(t=>{u.includes(t)?g.push(t):(s(t.pageNumber),f=t.pageNumber)}),g.length>0&&s(t.pages.length))}const y=[];return y.push("Detected "+e.length+" table of content pages"),e.length>0&&(y.push("TOC headline heights: "+JSON.stringify(d)),y.push("Found TOC headlines: "+(m-u.length+p.length)+"/"+m)),u.length>0&&(y.push("Found TOC headlines (by size): "+p.map(t=>t.lineItem.text())),y.push("Missing TOC headlines: "+u.filter(t=>!p.includes(t)).map(t=>t.lineItem.text()+"=>"+t.pageNumber))),new I({...t,globals:{...t.globals,tocPages:e,headlineTypeToHeightRange:d},messages:y})}};function Q(t,e){for(var s of t)if(X(s,e))return s;return null}function X(t,e){const s=new J({headline:e});var n=0;for(var r of t.items){const t=s.consume(r);if(t)return{lineIndex:n,headlineItems:t};n++}return null}var G=class{levelByMethod;uniqueFonts;constructor(){this.levelByMethod=null,this.uniqueFonts=[]}levelPageItems(t){if(!this.levelByMethod)if(this.calculateUniqueX(t).length>1)this.levelByMethod=this.levelByXDiff;else{const e=this.calculateUniqueFonts(t);e.length>1?(this.uniqueFonts=e,this.levelByMethod=this.levelByFont):this.levelByMethod=this.levelToZero}this.levelByMethod(t)}levelByXDiff(t){const e=this.calculateUniqueX(t);t.forEach(t=>{t.level=e.indexOf(t.lineItem.x)})}levelByFont(t){t.forEach(t=>{t.level=this.uniqueFonts.indexOf(t.lineItem.font)})}levelToZero(t){t.forEach(t=>{t.level=0})}calculateUniqueX(t){var e=t.reduce(function(t,e){return t.indexOf(e.lineItem.x)<0&&t.push(e.lineItem.x),t},[]);return e.sort((t,e)=>t-e),e}calculateUniqueFonts(t){return t.reduce(function(t,e){return t.indexOf(e.lineItem.font)<0&&t.push(e.lineItem.font),t},[])}},Z=class{lineItem;pageNumber;level;constructor(t){this.lineItem=t.lineItem,this.pageNumber=t.pageNumber,this.level=0}},tt=class extends A{constructor(){super("Detect List Items")}transform(t){var e=0,s=0;return t.pages.forEach(t=>{const n=[];t.items.forEach(t=>{if(n.push(t),!t.type){var r=t.text();if(a(t.words[0].string))if(e++,"-"===t.words[0].string)t.annotation=O,t.type=j.LIST;else{t.annotation=T;const e=t.words.map(t=>new C({...t}));e[0].string="-",n.push(new k({...t,words:e,annotation:E,type:j.LIST}))}else/^[\s]*[\d]*[.][\s].*$/g.test(r)&&(s++,t.annotation=O,t.type=j.LIST)}}),t.items=n}),new I({...t,messages:["Detected "+e+" plain list items.","Detected "+s+" numbered list items."]})}},et=class extends A{constructor(){super("Detect Headers")}transform(t){const{tocPages:e,headlineTypeToHeightRange:s,mostUsedHeight:n,mostUsedDistance:r,mostUsedFont:o,maxHeight:a}=t.globals,c=e.length>0;var l=0;const h=function(t,e){const s=/* @__PURE__ */new Set;return t.forEach(t=>{t.items.forEach(n=>{n.type||n.height!==e||s.add(t)})}),s}(t.pages,a),m=n+(a-n)/4;if(h.forEach(t=>{t.items.forEach(t=>{const e=t.height;!t.type&&e>m&&(t.type=e===a?j.H1:j.H2,t.annotation=O,l++)})}),c)Object.keys(s).forEach(e=>{var r=s[e];r.max>n&&t.pages.forEach(t=>{t.items.forEach(t=>{t.type||t.height!==r.max||(t.annotation=O,t.type=j.enumValueOf(e),l++)})})});else{const e=[];t.pages.forEach(t=>{t.items.forEach(t=>{!t.type&&t.height>n&&!i(t.text())&&(e.includes(t.height)||e.push(t.height))})}),e.sort((t,e)=>e-t),e.forEach((e,s)=>{if(s+2<=6){const n=j.headlineByLevel(2+s);t.pages.forEach(t=>{t.items.forEach(t=>{t.type||t.height!==e||i(t.text())||(l++,t.annotation=O,t.type=n)})})}})}var u=1;if(t.pages.forEach(t=>{t.items.forEach(t=>{t.type&&t.type.headline&&(u=Math.max(u,t.type.headlineLevel))})}),u<6){const e=j.headlineByLevel(u+1);t.pages.forEach(t=>{var s;t.items.forEach(t=>{!t.type&&t.height===n&&t.font!==o&&(!s||s.y<t.y||s.type&&s.type.headline||s.y-t.y>2*r)&&t.text()===t.text().toUpperCase()&&(l++,t.annotation=O,t.type=e),s=t})})}return new I({...t,messages:["Detected "+l+" headlines."]})}};var st=class extends f{items;constructor(t){super(t),this.items=[],t.items&&t.items.forEach(t=>this.addItem(t))}addItem(t){if(this.type&&t.type&&this.type!==t.type)throw new Error(`Adding item of type ${t.type.name} to block of type ${this.type.name}`);this.type||(this.type=t.type),t.parsedElements&&(this.parsedElements?this.parsedElements.add(t.parsedElements):this.parsedElements=t.parsedElements);const e=new k({...t});e.type=null,this.items.push(e)}},nt=class t extends x{constructor(e){if(super(e,st.name),this.constructor===t)throw new TypeError("Can not construct abstract class.")}completeTransform(t){return t.messages=[],t.pages.forEach(t=>{t.items=t.items.filter(t=>!t.annotation||t.annotation!==T),t.items.forEach(t=>t.annotation=null)}),t}},rt=class extends nt{constructor(){super("Gather Blocks")}transform(t){const{mostUsedDistance:e}=t.globals;var s=0,n=0;return t.pages.map(t=>{n+=t.items.length;const r=[];var o=new st({});const a=()=>{o.items.length>1&&(o.annotation=O),r.push(o),o=new st({}),s++};var i=function(t){var e=999;return t.forEach(t=>{e=Math.min(e,t.x)}),999===e?null:e}(t.items);t.items.forEach(t=>{o.items.length>0&&function(t,e,s,n){if(t.type&&t.type.mergeFollowingNonTypedItems&&!e.type)return!1;const r=t.items[t.items.length-1],o=function(t,e,s,n){const r=t.y-e.y;if(r<0-n/2)return!0;var o=n+1;t.x>s&&e.x>s&&(o=n+n/2);return r>o}(r,e,s,n);if(t.type&&t.type.mergeFollowingNonTypedItemsWithSmallDistance&&!e.type&&!o)return!1;if(e.type!==t.type)return!0;return e.type?!e.type.mergeToBlock:o}(o,t,i,e)&&a(),o.addItem(t)}),o.items.length>0&&a(),t.items=r}),new I({...t,messages:["Gathered "+s+" blocks out of "+n+" line items"]})}};var ot=class extends nt{constructor(){super("$1")}transform(t){const e=t.globals.mostUsedHeight??0;var s=0;return t.pages.forEach(t=>{var n=function(t){var e=999;return t.forEach(t=>{t.items.forEach(t=>{e=Math.min(e,t.x)})}),999===e?null:e}(t.items);t.items.forEach(t=>{!t.type&&function(t,e,s){if(0===e.length)return!1;if(1===e.length)return e[0].x>t&&e[0].height<=s+1;for(var n of e)if(n.x===t)return!1;return!0}(n,t.items,e)&&(t.annotation=O,t.type=j.CODE,s++)})}),new I({...t,messages:["Detected "+s+" code/quote items."]})}};var at,it=class extends nt{constructor(){super("Level Lists")}transform(t){var e=0,s=0;return t.pages.forEach(t=>{t.items.filter(t=>t.type===j.LIST).forEach(t=>{var n,r=0;const o={};var a=!1;t.items.forEach(t=>{n?t.x>n?(r++,o[t.x]=r):t.x<n&&(r=o[t.x]):o[t.x]=0,r>0&&(t.words=[new C({string:" ".repeat(3*r)})].concat(t.words),a=!0),n=t.x}),e++,a?(s++,t.annotation=S):t.annotation=b})}),new I({...t,messages:["Modified "+s+" / "+e+" list blocks."]})}},ct=class extends x{constructor(){super("To Text Blocks","TextBlock")}transform(t){return t.pages.forEach(t=>{const e=[];t.items.forEach(t=>{const s=t.type?t.type.name:"Unknown";e.push({category:s,text:j.blockToText(t)})}),t.items=e}),new I({...t})}},lt=class extends x{constructor(){super("To HTML","String")}transform(t){return t.pages.forEach(t=>{var e="";t.items.forEach(t=>{let s;s="TOC"===t.category?t.text:t.text.replace(/(\r\n|\n|\r)/gm,"\n"),"LIST"!==t.category&&(s=s.split("- ").join("")),"CODE"===t.category&&(s=s.split("<code>").join("").split("</code>").join("")),e+=`<p>${s}</p>\n\n`}),t.items=[e]}),new I({...t})}};async function ht(t,e={}){const{addPageNumbers:s=!1,addCitation:n=!0,liteParseOptions:r={}}=e,o="string"==typeof t?await w(t,{responseType:"arraybuffer",timeout:10}):t;let a;try{({LiteParse:a}=await import("@llamaindex/liteparse"))}catch(p){return{error:`method: 'liteparse' requires the optional @llamaindex/liteparse dependency (Node.js only): ${p.message}`}}const i=new a({quiet:!0,ocrEnabled:!1,ocrFailureFatal:!1,...r});let l;try{l=await i.parse(new Uint8Array(o))}catch(p){return{error:p.message}}const h=l.pages.reduce((t,e)=>{const n=e.text.split(/\n{2,}/).filter(t=>t.trim().length>0).map(t=>c(t).replace(/\n/g,"<br/>")).join("</p><p>");return t+`<p id="page-${e.pageNum}">${s?` [${e.pageNum}] `:""}${n}</p>`},"");let m,u;return n&&(u=l.creator||l.producer,m=l.pages[0]?.text.split("\n").find(t=>t.trim().length>0)),{author:u,title:m,html:h,format:"pdf"}}async function mt(t,e={}){const{addPageNumbers:s=!1,addCitation:n=!0,liteParseOptions:r={}}=e,o="string"==typeof t?await w(t,{responseType:"arraybuffer",timeout:10}):t;let a;try{a=await import("@llamaindex/liteparse-wasm"),await async function(t){at||(at=t.default()),await at}(a)}catch(p){return{error:`method: 'liteparse-wasm' requires the optional @llamaindex/liteparse-wasm dependency: ${p.message}`}}const i=new a.LiteParse({quiet:!0,ocrEnabled:!1,ocrFailureFatal:!1,...r});let l;try{l=await i.parse(new Uint8Array(o))}catch(p){return{error:p.message}}const h=l.pages.reduce((t,e)=>{const n=e.text.split(/\n{2,}/).filter(t=>t.trim().length>0).map(t=>c(t).replace(/\n/g,"<br/>")).join("</p><p>");return t+`<p id="page-${e.pageNum}">${s?` [${e.pageNum}] `:""}${n}</p>`},"");let m,u;return n&&(u=l.creator||l.producer,m=l.pages[0]?.text.split("\n").find(t=>t.trim().length>0)),{author:u,title:m,html:h,format:"pdf"}}var ut=null;async function pt(){return ut||(ut=import("https://cdn.jsdelivr.net/npm/pdfjs-serverless@1/+esm").catch(()=>import("pdfjs-serverless")).then(({resolvePDFJS:t})=>t())),ut}var dt=/\b(?:fig(?:ure)?s?|table|chart|graph|diagram|infographic|exhibit|illustration|plate|scheme)\s*\.?\s*(?:\d+(?:\.\d+)*|[ivxlcdm]+)\b/gi,ft=/^\s*\S[^\t\n]{0,60}?(?:\t+| {2,})\S[^\t\n]{0,60}?(?:\t+| {2,})\S/,gt=/(?:[-+]?[\d][\d.,]*\s*[%$€£]?\s+){3,}[-+]?[\d]/,yt=/[\uFFFD\u0000-\u0008\u000B\u000C\u000E-\u001F]/g;function wt(t,e={}){const{sparseTextThreshold:s=200,minTableRows:n=3,minNumericRows:r=2}=e,o=t.map((t,e)=>{const o=[],a=(t||"").replace(/\s+/g," ").trim();0===a.length?o.push("no-text"):a.length<s&&o.push("sparse-text");const i=(t||"").match(yt)?.length||0;a.length>0&&i/a.length>.05&&o.push("garbled-text");const c=[...(t||"").matchAll(dt)].map(t=>t[0].replace(/\s+/g," ").trim()),l=[...(t||"").matchAll(new RegExp(`^\\s*${dt.source}`,"gim"))].map(t=>t[0].trim());l.some(t=>/^table/i.test(t))&&o.push("table-caption"),l.some(t=>!/^table/i.test(t))&&o.push("figure-caption");const h=(t||"").split(/\r?\n/),m=h.filter(t=>ft.test(t)).length,u=h.filter(t=>gt.test(t)).length;return m>=n&&o.push("table-rows"),u>=r&&o.push("numeric-grid"),{page:e+1,needsOcr:o.length>0,reasons:o,captions:c}}),a=o.filter(t=>t.needsOcr).map(t=>t.page);return{needsOcr:a.length>0,pagesNeedingOcr:a,pages:o}}var xt="onnx-community/granite-docling-258M-ONNX",vt="Convert this page to docling.",Et=null;async function Tt(t,e={}){const{processorUrl:s,prompt:n=vt,maxTokens:r=4096}=e;if(s){const e=await fetch(`${s.replace(/\/$/,"")}/api/v1/convert-base64`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({imageBase64:t,mimeType:"image/png",prompt:n,maxTokens:r})}),o=await e.json();if(!e.ok||!o?.success)throw new Error(o?.error||`Processor error ${e.status}`);return o.result}const{model:o,processor:a,lib:i}=await async function(){return Et||(Et=(async()=>{const t=await import("@huggingface/transformers"),e=await t.AutoProcessor.from_pretrained(xt);return{model:await t.AutoModelForVision2Seq.from_pretrained(xt,{dtype:"fp32"}),processor:e,lib:t}})()),Et}(),c=await i.load_image(`data:image/png;base64,${t}`),l=[{role:"user",content:[{type:"image"},{type:"text",text:n}]}],h=await a(a.apply_chat_template(l,{add_generation_prompt:!0}),[c],{do_image_splitting:!0}),m=await o.generate({...h,max_new_tokens:r}),[u]=a.batch_decode(m.slice(null,[h.input_ids.dims.at(-1),null]),{skip_special_tokens:!0});return u}async function bt(t,e=2){const s=t.getViewport({scale:e}),n=await async function(t,e){if("undefined"!=typeof document){const s=document.createElement("canvas");return s.width=t,s.height=e,s}try{return(await import("@napi-rs/canvas")).createCanvas(t,e)}catch{}if("undefined"!=typeof OffscreenCanvas)return new OffscreenCanvas(t,e);throw new Error("No canvas available to rasterize PDF pages — install @napi-rs/canvas in Node.js, or run in a browser/Worker with OffscreenCanvas")}(Math.ceil(s.width),Math.ceil(s.height)),r=n.getContext("2d");return await t.render({canvasContext:r,viewport:s}).promise,async function(t){if("function"==typeof t.toBuffer)return t.toBuffer("image/png").toString("base64");if("function"==typeof t.convertToBlob){const e=await t.convertToBlob({type:"image/png"}),s=new Uint8Array(await e.arrayBuffer());let n="";for(const t of s)n+=String.fromCharCode(t);return btoa(n)}return t.toDataURL("image/png").split(",")[1]}(n)}async function Ot(t,e,s={}){const n=/* @__PURE__ */new Map;for(const o of e)try{const e=await Tt(await bt(await t.getPage(o),s.scale),s);n.set(o,St(e))}catch(r){console.error(`Docling OCR failed for page ${o}:`,r)}return n}function St(t){let e=(t||"").replace(/<\/?doctag>/g,"").replace(/<loc_\d+>/g,"").replace(/<page_break>/g,"").replace(/<end_of_utterance>/g,"").replace(/<page_(?:header|footer)>[\s\S]*?<\/page_(?:header|footer)>/g,"");e=e.replace(/<otsl>([\s\S]*?)<\/otsl>/g,(t,e)=>function(t){return`<table>${t.split("<nl>").map(t=>t.trim()).filter(Boolean).map(t=>{const e=[...t.matchAll(/<(fcel|ched|rhed|ecel|lcel|ucel|xcel)>([^<]*)/g)];return e.length?`<tr>${e.map(([,t,e])=>{const s="ched"===t||"rhed"===t?"th":"td";return`<${s}>${e.trim()}</${s}>`}).join("")}</tr>`:""}).filter(Boolean).join("")}</table>`}(e));for(const[s,n,r]of[[/<title>([\s\S]*?)<\/title>/g,"<h1>","</h1>"],[/<section_header_level_1>([\s\S]*?)<\/section_header_level_1>/g,"<h2>","</h2>"],[/<section_header_level_2>([\s\S]*?)<\/section_header_level_2>/g,"<h3>","</h3>"],[/<section_header_level_3>([\s\S]*?)<\/section_header_level_3>/g,"<h4>","</h4>"],[/<section_header_level_[4-9]>([\s\S]*?)<\/section_header_level_[4-9]>/g,"<h5>","</h5>"],[/<(?:text|paragraph)>([\s\S]*?)<\/(?:text|paragraph)>/g,"<p>","</p>"],[/<caption>([\s\S]*?)<\/caption>/g,"<figcaption>","</figcaption>"],[/<(?:picture|chart)>([\s\S]*?)<\/(?:picture|chart)>/g,"<figure>","</figure>"],[/<code>([\s\S]*?)<\/code>/g,"<pre><code>","</code></pre>"],[/<formula>([\s\S]*?)<\/formula>/g,'<code class="formula">',"</code>"],[/<footnote>([\s\S]*?)<\/footnote>/g,'<p class="footnote">',"</p>"],[/<list_item>([\s\S]*?)<\/list_item>/g,"<li>","</li>"],[/<unordered_list>([\s\S]*?)<\/unordered_list>/g,"<ul>","</ul>"],[/<ordered_list>([\s\S]*?)<\/ordered_list>/g,"<ol>","</ol>"]])e=e.replace(s,(t,e)=>`${n}${e.trim()}${r}`);return e=e.replace(/<\/?(?:[a-z][a-z0-9]*_[a-z0-9_]+|otsl|smiles)>/g,""),e.trim()}async function Lt(t,e={}){const s="string"==typeof t?await w(t,{responseType:"arraybuffer",timeout:10}):t,{LiteParse:n}=await import("@llamaindex/liteparse"),r=await new n({quiet:!0,...e.liteParseOptions}).isComplex(new Uint8Array(s));return{needsOcr:r.some(t=>t.needsOcr),pages:r,reasons:[...new Set(r.flatMap(t=>t.reasons))]}}async function It(t,e={}){if("liteparse"===e.method){const{method:s,...n}=e;return ht(t,n)}if("liteparse-wasm"===e.method){const{method:s,...n}=e;return mt(t,n)}var{addPageNumbers:s=!1,addCitation:n=!0}=e;const r=e.processor??"frontend",o=/^https?:\/\//i.test(r),a=o?"docling":r,i={...e.doclingOptions,processorUrl:o?r:e.processorUrl};var c="string"==typeof t?await w(t,{responseType:"arraybuffer",timeout:10}):t;let l;try{const{getDocument:t}=await pt();l=await t({data:new Uint8Array(c),useSystemFonts:!0,verbosity:0}).promise}catch(k){return{error:k.message}}const h=[...Array(l.numPages).keys()].map(t=>new y({index:t}));let m,f={};for(let d=1;d<=l.numPages;d++){const t=await l.getPage(d),e=await t.getTextContent();if(!(Object.keys(f).length<10)){m=p(f);break}f=u(f,t.pageNumber-1,e.items)}let x=m?m.pageNum:0;for(let u=1;u<=l.numPages;u++){const t=await l.getPage(u);await t.getOperatorList();const e=t.getViewport({scale:1});let s=await t.getTextContent();m&&t.pageIndex>=m.pageIndex&&(s=d(s,x),x++);const n=s.items.map(t=>{const s=[1,0,0,1,0,0];for(let o=0;o<6;o++)s[o]+=t.transform[o]*e.transform[o%2?3:0],o%2&&(s[o+1]+=t.transform[o]*e.transform[1]);const n=Math.sqrt(s[2]*s[2]+s[3]*s[3]),r=t.height/n;return new g({x:Math.round(t.transform[4]),y:Math.round(t.transform[5]),width:Math.round(t.width),height:Math.round(r<=1?t.height:r),text:t.str,font:t.fontName})});h[t.pageNumber-1].items=n}const v=h.map(t=>Object.values(t.items.reduce((t,e)=>((t[e.y]=t[e.y]||[]).push(e.text),t),{})).map(t=>t.join(" ")).join("\n"));var E=new I({pages:h});let T;[new U,new q,new Y,new V,new K,new et,new tt,new rt,new ot,new it,new ct,new lt].forEach(t=>{T&&(E=T.completeTransform(E)),E=t.transform(E),T=t});var b=E.pages.map((t,e)=>`<p id="page-${e+1}">${s?` [${e+1}] `:""}${t.items.join('</p><p id="page-'+e+'">')}</p>`);const O=wt(v,e.ocrScanOptions);if("docling"===a||"hybrid"===a){const t="docling"===a?b.map((t,e)=>e+1):O.pagesNeedingOcr,e=await Ot(l,t,i);for(const[n,r]of e)b[n-1]=`<section class="ocr-page" id="page-${n}">${s?` [${n}] `:""}${r}</section>`}var S=b.join("");if(n){var{Author:L,Title:C}=(await l.getMetadata()).info;C=S.slice(0,400).match(/<h[0-9]>(.*?)<\/h[0-9]>/)?.[1]||C}return{author:L,title:C,html:S,format:"pdf",processor:a,ocrScan:O}}export{It as convertPDFToHTML,ht as convertPDFToHTMLWithLiteParse,mt as convertPDFToHTMLWithLiteParseWasm,Lt as detectPdfNeedsOcr,St as doctagsToHtml,pt as loadPdfJs,Tt as ocrImageWithDocling,Ot as ocrPdfPagesWithDocling,bt as renderPdfPageToPngBase64,wt as scanPagesForOCR};
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @fileoverview Lazy loader for the slim serverless PDF.js build.
3
+ *
4
+ * The package deliberately does NOT depend on `pdfjs-dist`: PDF.js is pulled
5
+ * at runtime from jsDelivr's ESM build of
6
+ * [pdfjs-serverless](https://github.com/johannschopplich/pdfjs-serverless) —
7
+ * a zero-dependency, single-file (~1.6 MB minified) redistribution of Mozilla
8
+ * PDF.js that works in Workers/edge runtimes, Node.js, and browsers. Pinned
9
+ * to the major version so compatible patch/minor releases update
10
+ * automatically. This keeps `extract-pdf`'s default export slim: nothing
11
+ * PDF.js-related is bundled or installed until a document is actually parsed.
12
+ */
13
+ /**
14
+ * Resolves the PDF.js API (`getDocument`, ...) from the pdfjs-serverless CDN
15
+ * build, caching the module after the first call. Node.js and Bun cannot
16
+ * import remote URLs, so when the CDN import throws we fall back to the
17
+ * locally-installed `pdfjs-serverless` optional dependency.
18
+ */
19
+ export declare function loadPdfJs(): Promise<any>;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "extract-pdf",
3
- "version": "0.1.260",
4
- "description": "Convert a PDF (URL or ArrayBuffer) into clean HTML with structural tagging — headings, lists, footnotes, code blocks, bold/italic. Works in Node.js, Cloudflare Workers, and browser environments.",
3
+ "version": "0.1.261",
4
+ "description": "Convert a PDF (URL or ArrayBuffer) into clean HTML with structural tagging — headings, lists, footnotes, code blocks, bold/italic. Slim by default (PDF.js loads at runtime from the pdfjs-serverless CDN build), with optional Granite Docling OCR for pages with infographics/tables — in-process, hybrid, or via a remote processor URL. Works in Node.js, Cloudflare Workers, and browser environments.",
5
5
  "author": "vtempest <grokthiscontact@gmail.com>",
6
6
  "license": "rights.institute/PROSPER",
7
7
  "type": "module",
@@ -17,19 +17,31 @@
17
17
  },
18
18
  "files": [
19
19
  "dist",
20
- "src"
20
+ "src",
21
+ "server"
21
22
  ],
22
23
  "scripts": {
23
24
  "build": "vite build",
24
- "prepare": "vite build",
25
25
  "test": "bun test",
26
26
  "test:coverage": "bun test --coverage --coverage-reporter=lcov --coverage-reporter=text",
27
+ "serve:docling": "node server/server.js",
28
+ "dev:docling": "node --watch server/server.js",
27
29
  "ship": "npm run build && npx standard-version --release-as patch; rm -f CHANGELOG.md; npm publish"
28
30
  },
29
- "dependencies": {},
31
+ "dependencies": {
32
+ "grab-url": "^1.6.22"
33
+ },
30
34
  "optionalDependencies": {
35
+ "@hono/node-server": "^1.8.2",
36
+ "@hono/swagger-ui": "^0.2.1",
37
+ "@hono/zod-openapi": "^0.9.8",
38
+ "@huggingface/transformers": "^3.0.0",
31
39
  "@llamaindex/liteparse": "^2.10.0",
32
- "@llamaindex/liteparse-wasm": "^2.11.0"
40
+ "@llamaindex/liteparse-wasm": "^2.11.0",
41
+ "@napi-rs/canvas": "^0.1.65",
42
+ "hono": "^4.0.0",
43
+ "pdfjs-serverless": "^1.1.0",
44
+ "zod": "^3.22.4"
33
45
  },
34
46
  "devDependencies": {
35
47
  "terser": "^5.46.0",
@@ -0,0 +1,96 @@
1
+ /**
2
+ * @file model.js
3
+ * @description Singleton loader for the Granite Docling ONNX vision model and processor.
4
+ */
5
+ import {
6
+ AutoProcessor,
7
+ AutoModelForVision2Seq,
8
+ load_image,
9
+ TextStreamer,
10
+ } from "@huggingface/transformers";
11
+
12
+ export { load_image, TextStreamer };
13
+
14
+ const MODEL_ID = "onnx-community/granite-docling-258M-ONNX";
15
+
16
+ /** @type {any} */
17
+ let model = null;
18
+ /** @type {any} */
19
+ let processor = null;
20
+ /** @type {Promise<{model: any, processor: any}> | null} */
21
+ let initializationPromise = null;
22
+
23
+ /**
24
+ * Returns the loaded model and processor, initializing them on first call.
25
+ * Subsequent calls return the cached instance without re-loading.
26
+ *
27
+ * @returns {Promise<{model: any, processor: any}>}
28
+ */
29
+ export async function initializeModel() {
30
+ if (model && processor) return { model, processor };
31
+ if (initializationPromise) return initializationPromise;
32
+
33
+ initializationPromise = (async () => {
34
+ console.log("Initializing Granite Docling model...");
35
+ processor = await AutoProcessor.from_pretrained(MODEL_ID);
36
+ model = await AutoModelForVision2Seq.from_pretrained(MODEL_ID, {
37
+ dtype: "fp32",
38
+ });
39
+ console.log("Model initialized successfully");
40
+ return { model, processor };
41
+ })();
42
+
43
+ return initializationPromise;
44
+ }
45
+
46
+ /**
47
+ * Returns true once the model and processor have been loaded.
48
+ *
49
+ * @returns {boolean}
50
+ */
51
+ export function isModelLoaded() {
52
+ return model !== null && processor !== null;
53
+ }
54
+
55
+ /**
56
+ * Runs the vision model on a pre-loaded image and returns the generated text.
57
+ *
58
+ * @param {object} opts
59
+ * @param {any} opts.image - Image object returned by `load_image`
60
+ * @param {string} opts.prompt - Instruction text sent alongside the image
61
+ * @param {number} opts.maxTokens - Maximum tokens to generate
62
+ * @param {boolean} opts.streaming - Whether to collect tokens via TextStreamer
63
+ * @returns {Promise<{generatedText: string, generated_ids: any}>}
64
+ */
65
+ export async function generateFromImage({ image, prompt, maxTokens, streaming }) {
66
+ const { model: m, processor: p } = await initializeModel();
67
+
68
+ const messages = [{
69
+ role: "user",
70
+ content: [{ type: "image" }, { type: "text", text: prompt }],
71
+ }];
72
+
73
+ const text = p.apply_chat_template(messages, { add_generation_prompt: true });
74
+ const inputs = await p(text, [image], { do_image_splitting: true });
75
+
76
+ let generatedText = "";
77
+ let generated_ids;
78
+
79
+ if (streaming) {
80
+ const streamer = new TextStreamer(p.tokenizer, {
81
+ skip_prompt: true,
82
+ skip_special_tokens: false,
83
+ on_finalized_text: (chunk) => { generatedText += chunk; },
84
+ });
85
+ generated_ids = await m.generate({ ...inputs, max_new_tokens: maxTokens, streamer });
86
+ } else {
87
+ generated_ids = await m.generate({ ...inputs, max_new_tokens: maxTokens });
88
+ const texts = p.batch_decode(
89
+ generated_ids.slice(null, [inputs.input_ids.dims.at(-1), null]),
90
+ { skip_special_tokens: true },
91
+ );
92
+ generatedText = texts[0];
93
+ }
94
+
95
+ return { generatedText, generated_ids };
96
+ }
@@ -0,0 +1,91 @@
1
+ /**
2
+ * @file routes.js
3
+ * @description OpenAPI route definitions for the Granite Docling API.
4
+ * Handlers are registered in pdf2html.js via `app.openapi(route, handler)`.
5
+ */
6
+ import { createRoute } from "@hono/zod-openapi";
7
+ import {
8
+ ConvertImageBodySchema,
9
+ ConvertImageBase64BodySchema,
10
+ ConvertImageResponseSchema,
11
+ ErrorResponseSchema,
12
+ HealthResponseSchema,
13
+ } from "./schemas.js";
14
+
15
+ /** Reusable 400/500 error response spec. */
16
+ const errorResponses = {
17
+ 400: {
18
+ content: { "application/json": { schema: ErrorResponseSchema } },
19
+ description: "Bad request",
20
+ },
21
+ 500: {
22
+ content: { "application/json": { schema: ErrorResponseSchema } },
23
+ description: "Internal server error",
24
+ },
25
+ };
26
+
27
+ /**
28
+ * POST /api/v1/convert
29
+ * Converts an image URL to docling format.
30
+ */
31
+ export const convertImageRoute = createRoute({
32
+ method: "post",
33
+ path: "/api/v1/convert",
34
+ tags: ["Document Conversion"],
35
+ summary: "Convert image to docling format",
36
+ description: "Converts an image URL to docling format using the Granite Docling model",
37
+ request: {
38
+ body: {
39
+ content: { "application/json": { schema: ConvertImageBodySchema } },
40
+ },
41
+ },
42
+ responses: {
43
+ 200: {
44
+ content: { "application/json": { schema: ConvertImageResponseSchema } },
45
+ description: "Successful conversion",
46
+ },
47
+ ...errorResponses,
48
+ },
49
+ });
50
+
51
+ /**
52
+ * POST /api/v1/convert-base64
53
+ * Converts a base64-encoded image to docling format.
54
+ */
55
+ export const convertImageBase64Route = createRoute({
56
+ method: "post",
57
+ path: "/api/v1/convert-base64",
58
+ tags: ["Document Conversion"],
59
+ summary: "Convert base64 image to docling format",
60
+ description: "Converts a base64 encoded image to docling format using the Granite Docling model",
61
+ request: {
62
+ body: {
63
+ content: { "application/json": { schema: ConvertImageBase64BodySchema } },
64
+ },
65
+ },
66
+ responses: {
67
+ 200: {
68
+ content: { "application/json": { schema: ConvertImageResponseSchema } },
69
+ description: "Successful conversion",
70
+ },
71
+ ...errorResponses,
72
+ },
73
+ });
74
+
75
+ /**
76
+ * GET /health
77
+ * Returns service status, model readiness, and uptime.
78
+ */
79
+ export const healthRoute = createRoute({
80
+ method: "get",
81
+ path: "/health",
82
+ tags: ["System"],
83
+ summary: "Health check",
84
+ description: "Check if the service is running and model is loaded",
85
+ responses: {
86
+ 200: {
87
+ content: { "application/json": { schema: HealthResponseSchema } },
88
+ description: "Health check response",
89
+ },
90
+ },
91
+ });
@@ -0,0 +1,91 @@
1
+ /**
2
+ * @file schemas.js
3
+ * @description Zod schemas shared across route definitions and handlers.
4
+ */
5
+ import { z } from "@hono/zod-openapi";
6
+
7
+ /**
8
+ * Request body for the URL-based conversion endpoint.
9
+ */
10
+ export const ConvertImageBodySchema = z.object({
11
+ imageUrl: z.string().url().describe("URL of the image to convert"),
12
+ prompt: z
13
+ .string()
14
+ .optional()
15
+ .default("Convert this page to docling.")
16
+ .describe("Custom prompt for conversion"),
17
+ maxTokens: z
18
+ .number()
19
+ .int()
20
+ .min(1)
21
+ .max(8192)
22
+ .optional()
23
+ .default(4096)
24
+ .describe("Maximum number of tokens to generate"),
25
+ streaming: z
26
+ .boolean()
27
+ .optional()
28
+ .default(false)
29
+ .describe("Enable streaming response"),
30
+ });
31
+
32
+ /**
33
+ * Request body for the base64-encoded image conversion endpoint.
34
+ */
35
+ export const ConvertImageBase64BodySchema = z.object({
36
+ imageBase64: z.string().describe("Base64 encoded image"),
37
+ mimeType: z
38
+ .string()
39
+ .optional()
40
+ .default("image/png")
41
+ .describe("MIME type of the image"),
42
+ prompt: z
43
+ .string()
44
+ .optional()
45
+ .default("Convert this page to docling.")
46
+ .describe("Custom prompt for conversion"),
47
+ maxTokens: z
48
+ .number()
49
+ .int()
50
+ .min(1)
51
+ .max(8192)
52
+ .optional()
53
+ .default(4096)
54
+ .describe("Maximum number of tokens to generate"),
55
+ streaming: z
56
+ .boolean()
57
+ .optional()
58
+ .default(false)
59
+ .describe("Enable streaming response"),
60
+ });
61
+
62
+ /**
63
+ * Successful conversion response.
64
+ */
65
+ export const ConvertImageResponseSchema = z.object({
66
+ success: z.boolean(),
67
+ result: z.string().describe("Converted docling text"),
68
+ metadata: z.object({
69
+ processingTime: z.number().describe("Processing time in milliseconds"),
70
+ tokenCount: z.number().optional().describe("Number of tokens generated"),
71
+ }),
72
+ });
73
+
74
+ /**
75
+ * Error response returned by all endpoints on failure.
76
+ */
77
+ export const ErrorResponseSchema = z.object({
78
+ success: z.boolean().default(false),
79
+ error: z.string(),
80
+ code: z.string().optional(),
81
+ });
82
+
83
+ /**
84
+ * Health check response.
85
+ */
86
+ export const HealthResponseSchema = z.object({
87
+ status: z.string(),
88
+ modelLoaded: z.boolean(),
89
+ uptime: z.number(),
90
+ version: z.string(),
91
+ });