1window.pdfEditor = { 2 _doc: null, 3 _pageCount: 0, 4 _lib: null, 5 6 _ensurePdfJs: async function () { 7 if (this._lib) return true; 8 try { 9 var lib = await import('/lib/pdfjs/pdf.min.mjs'); 10 lib.GlobalWorkerOptions.workerSrc = '/lib/pdfjs/pdf.worker.min.mjs'; 11 this._lib = lib; 12 console.log('PDF.js loaded successfully'); 13 return true; 14 } catch (e) { 15 console.error('Failed to load PDF.js:', e); 16 return false; 17 } 18 }, 19 20 loadDocument: async function (url) { 21 var ready = await this._ensurePdfJs(); 22 if (!ready) return false; 23 24 try { 25 var response = await fetch(url); 26 if (!response.ok) { 27 console.error('PDF fetch failed:', response.status); 28 return false; 29 } 30 var data = await response.arrayBuffer(); 31 this._doc = await this._lib.getDocument({ data: data }).promise; 32 this._pageCount = this._doc.numPages; 33 return true; 34 } catch (e) { 35 console.error('Failed to load PDF document:', e); 36 return false; 37 } 38 }, 39 40 loadDocumentFromBytes: async function (byteArray) { 41 var ready = await this._ensurePdfJs(); 42 if (!ready) return false; 43 44 try { 45 var data = byteArray instanceof Uint8Array ? byteArray : new Uint8Array(byteArray); 46 this._doc = await this._lib.getDocument({ data: data }).promise; 47 this._pageCount = this._doc.numPages; 48 console.log('PDF loaded from bytes, pages:', this._pageCount); 49 return true; 50 } catch (e) { 51 console.error('Failed to load PDF from bytes:', e); 52 return false; 53 } 54 }, 55 56 getPageCount: function () { 57 return this._pageCount; 58 }, 59 60 renderPage: async function (pageNum, canvasId, scale) { 61 if (!this._doc) return { width: 0, height: 0 }; 62 try { 63 var page = await this._doc.getPage(pageNum); 64 var viewport = page.getViewport({ scale: scale || 1.0 }); 65 var canvas = document.getElementById(canvasId); 66 if (!canvas) return { width: 0, height: 0 }; 67 68 canvas.width = viewport.width; 69 canvas.height = viewport.height; 70 var ctx = canvas.getContext('2d'); 71 72 await page.render({ canvasContext: ctx, viewport: viewport }).promise; 73 return { width: viewport.width, height: viewport.height }; 74 } catch (e) { 75 console.error('Failed to render page:', e); 76 return { width: 0, height: 0 }; 77 } 78 }, 79 80 getPageDimensions: async function (pageNum) { 81 if (!this._doc) return { width: 0, height: 0 }; 82 try { 83 var page = await this._doc.getPage(pageNum); 84 var viewport = page.getViewport({ scale: 1.0 }); 85 return { width: viewport.width, height: viewport.height }; 86 } catch (e) { 87 return { width: 0, height: 0 }; 88 } 89 }, 90 91 getContainerWidth: function (containerId) { 92 var el = document.querySelector('.pdf-editor-canvas-area'); 93 if (!el) return 600; 94 return el.clientWidth - 48; // subtract padding 95 }, 96 97 getClickPercent: function (canvasId, clientX, clientY) { 98 var canvas = document.getElementById(canvasId); 99 if (!canvas) return null; 100 var rect = canvas.getBoundingClientRect(); 101 var x = ((clientX - rect.left) / rect.width) * 100; 102 var y = ((clientY - rect.top) / rect.height) * 100; 103 return { x: Math.max(0, Math.min(100, x)), y: Math.max(0, Math.min(100, y)) }; 104 }, 105 106 destroy: function () { 107 if (this._doc) { 108 this._doc.destroy(); 109 this._doc = null; 110 } 111 this._pageCount = 0; 112 } 113};
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.