1const types=["jpg","jpeg","png","webp","bmp","tiff","heic","heif","pdf","gif"];const validTypes=[...types.map(type=>`image/${type}`),"application/pdf"];let heicScriptPromise=null;let tiffScriptPromise=null;let noNeedToShowPopup=!1;export const scriptToRequire={tiff:{id:"jsTiff",src:"https://cdn.rawgit.com/seikichi/tiff.js/master/tiff.min.js",},heic:{id:"jsHeic",src:BaseUrl+"/web_assets/frontend/script/index.min.js",},pdf:{src:"https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.10.377/pdf.min.js",id:"pdfjs"},zip:{id:"jsZip",src:"https://cdnjs.cloudflare.com/ajax/libs/jszip/3.5.0/jszip.min.js",},fileSaver:{id:"fileSaver",src:"https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.0/FileSaver.min.js",},cropperJs:{id:"cropperJs",src:`https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.13/cropper.min.js`,},cropperCSS:{id:"cropperCSS",src:`https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.13/cropper.min.css`,}};const excludeDroppedFolders=(dataTransfer)=>{const items=dataTransfer.items;if(!items||!items.length||typeof items[0].webkitGetAsEntry!=="function"){return{files:dataTransfer.files,hasFolder:!1}} 2const files=[];let hasFolder=!1;for(let i=0;i<items.length;i++){if(items[i].kind!=="file")continue;const entry=items[i].webkitGetAsEntry();if(entry&&entry.isDirectory){hasFolder=!0;continue} 3const file=items[i].getAsFile();if(file)files.push(file);} 4return{files,hasFolder}};export const handleDragAndDropEvents=(selector,onFilesDropped)=>{const dragZone=$(selector);let dragCounter=0;const updateUI=(isDragging)=>{$(".upload-area").toggleClass("upload-area-hover",isDragging);$(".drop_text").toggleClass("hidden",!isDragging);$(".browse_area").toggle(!isDragging);dragZone.css("background",isDragging?"#ffffff":"#ffffff")};dragZone.on("dragenter",(e)=>{e.preventDefault();if(++dragCounter===1)updateUI(!0);});dragZone.on("dragleave",(e)=>{e.preventDefault();if(--dragCounter===0)updateUI(!1);});dragZone.on("dragover",(e)=>{e.preventDefault()});dragZone.on("drop",(e)=>{e.preventDefault();dragCounter=0;updateUI(!1);const{files,hasFolder}=excludeDroppedFolders(e.originalEvent.dataTransfer);if(hasFolder){showAlertBox(file_type_title,file_type_desc,"file-type")} 5if(!files.length)return;if(typeof onFilesDropped==="function"){onFilesDropped(files)}})};export const appendFilesToArray=async(files,maxFileSize=5,validImageTypes=validTypes,onlyFile=!1,batchSize=3,allowHeif=!1)=>{files=Object.values(files);let results=[];let lastError=null;noNeedToShowPopup=!1;const validFiles=[];for(const file of files){let fileType=file.type;const sizeInMB=file.size/(1024*1024);const isHeicFile=file.name.toLowerCase().endsWith(".heic")||file.name.toLowerCase().endsWith(".heif");if(isHeicFile&&allowHeif){fileType="image/heif"} 6if(!(validImageTypes.includes(fileType)||(!isHeicFile&&fileType===""))){lastError={title:file_type_title,desc:file_type_desc,type:"file-type"};continue} 7if(sizeInMB>
7maxFileSize){lastError={title:file_size_title,desc:file_size_desc,type:"limit_exceed"};continue} 8validFiles.push(file)} 9for(let i=0;i<validFiles.length;i+=batchSize){const batch=validFiles.slice(i,i+batchSize);const batchResults=await Promise.allSettled(batch.map(file=>processSingleFile(file,onlyFile)));for(const res of batchResults){if(res.status==="fulfilled"&&res.value){if(Array.isArray(res.value)){results.push(...res.value)}else{results.push(res.value)}}}} 10if(lastError){showAlertBox(lastError.title,lastError.desc,lastError.type)} 11return results};const processSingleFile=async(file,onlyFile)=>{try{if(onlyFile){return{file}} 12let base64=await fileToBase64(file);switch(file.type){case "image/tiff":await loadTiffOnce();base64=await convertTiffToJpgBase64(file);break;case "image/webp":base64=await convertWebpFileToJpgBase64(file);break;case "application/pdf":return await convertPdfToImage(file);case "image/heic":case "image/heif":await loadHeicOnce();base64=await convertHeicToImg(file);if(base64.includes("application/octet-stream")){base64=base64.replace("application/octet-stream","image/jpg")} 13break;case "":if(file.name.toLowerCase().endsWith('.heic')||file.name.toLowerCase().endsWith('.heif')){await loadHeicOnce();base64=await convertHeicToImg(file);if(base64.includes("application/octet-stream")){base64=base64.replace("application/octet-stream","image/jpg")}} 14break;default:if(base64.includes("application/octet-stream")){base64=base64.replace("application/octet-stream","image/jpg")} 15break} 16return{base64,file}}catch(err){console.error("Error processing file:",file.name,err);showAlertBox(invalidFile,upload_valid_file,"file-type");return null}};function loadHeicOnce(){if(!heicScriptPromise){heicScriptPromise=loadScript("https://cdn.jsdelivr.net/npm/[email protected]/dist/iife/heic-to.js","heic-to")} 17return heicScriptPromise} 18function loadTiffOnce(){if(!tiffScriptPromise){tiffScriptPromise=loadScript(scriptToRequire.tiff.src,scriptToRequire.tiff.id)} 19return tiffScriptPromise} 20const fileToBase64=(file)=>{return new Promise((resolve,reject)=>{const reader=new FileReader();reader.onload=e=>resolve(e.target.result);reader.onerror=reject;reader.readAsDataURL(file)})};export const convertTiffToJpgBase64=async(tiffFile)=>{if(typeof Tiff==="undefined"){for(let i=0;i<20;i++){if(typeof Tiff!=="undefined")break;await new Promise(resolve=>setTimeout(resolve,50))}} 21return new Promise((resolve,reject)=>{const reader=new FileReader();reader.onload=(e)=>{try{const buffer=e.target.result;if(typeof Tiff==="undefined"){throw new Error("Tiff library failed to load or is not defined.")} 22const tiff=new Tiff({buffer:buffer});const canvas=tiff.toCanvas(0);const jpegCanvas=document.createElement('canvas');const ctx=jpegCanvas.getContext('2d');jpegCanvas.width=canvas.width;jpegCanvas.height=canvas.height;ctx.drawImage(canvas,0,0);const jpegBase64=jpegCanvas.toDataURL('image/jpeg');resolve(jpegBase64)}catch(error){reject(error)}};reader.onerror=(error)=>reject(error);reader.readAsArrayBuffer(tiffFile)})};export const convertWebpFileToJpgBase64=(webpFile)=>{return new Promise((resolve,reject)=>{const reader=new FileReader();reader.onload=(e)=>{const img=new Image();img.onload=()=>{const canvas=document.createElement('canvas');canvas.width=img.width;canvas.height=img.height;const ctx=canvas.getContext('2d');ctx.drawImage(img,0,0);const jpgBase64=canvas.toDataURL('image/jpeg');resolve(jpgBase64)};img.onerror=(error)=>reject(error);img.src=e.target.result};reader.onerror=(error)=>reject(error);reader.readAsDataURL(webpFile)})};export const convertHeicToImg=async(file)=>{if(!file)return null;const isHeic=file.type==='image/heic'||file.type==='image/heif'||/\.heic$/i.test(file.name)||/\.heif$/i.test(file.name);if(!isHeic){return await blobToBase64(file)} 23if(typeof HeicTo==="undefined"){await new Promise(resolve=>setTimeout(resolve,800))} 24try{const convertedBlob=await HeicTo({blob:file,format:'JPEG',quality:0.92});return await blobToBase64(convertedBlob)}catch(err){console.warn("Falling back to original file");return await blobToBase64(file)}};const blobToBase64=(blob)=>{return new Promise((resolve,reject)=>{const reader=new FileReader();reader.onload=()=>resolve(reader.result);reader.onerror=()=>reject(new Error("FileReader failed"));
24reader.readAsDataURL(blob)})};export const convertPdfToImage=async(file,check=!0,extractPage=!1)=>{if(noNeedToShowPopup)return;let lastError=null;const base64Files=[];try{await loadScript(scriptToRequire.pdf.src,scriptToRequire.pdf.id);const pdfData=new Uint8Array(await file.arrayBuffer());const loadingTask=pdfjsLib.getDocument({data:pdfData});let pdf;try{pdf=await loadingTask.promise}catch(loadErr){let message=upload_valid_file;if(loadErr?.name==="PasswordException"){message=passwordProtected}else if(loadErr?.name==="InvalidPDFException"){message=corruptedFile}else if(loadErr?.message?.toLowerCase().includes("missing pdf")){message="The PDF file appears to be missing or empty."} 25lastError={title:invalidFile,desc:message,type:"file-type"}} 26if(!pdf){if(lastError)showAlertBox(lastError.title,lastError.desc,lastError.type);return base64Files} 27const numPages=pdf.numPages;const alreadySelected=document.querySelectorAll('.files-item').length;const remainingLimit=PER_REQUEST_LIMIT-alreadySelected;if(check&&remainingLimit<=0){lastError={title:"File Limit Exceeded",desc:`Free User can upload ${PER_REQUEST_LIMIT} files per submission.`,type:"limit_exceed"};if(lastError)showAlertBox(lastError.title,lastError.desc,lastError.type);return base64Files} 28const iterationCount=check?Math.min(numPages,remainingLimit):numPages;if(check&&numPages>remainingLimit){if(noNeedToShowPopup)return;noNeedToShowPopup=!0;lastError={title:max_file_upload_limit,desc:max_file_upload_limit_desc,type:"limit_exceed"}} 29for(let pageNum=1;pageNum<=iterationCount;pageNum++){try{const page=await pdf.getPage(pageNum);if(extractPage){base64Files.push({page})}else{const scale=1.5;const viewport=page.getViewport({scale});const canvas=document.createElement('canvas');const context=canvas.getContext('2d');canvas.height=viewport.height;canvas.width=viewport.width;await page.render({canvasContext:context,viewport}).promise;const base64=canvas.toDataURL('image/jpeg');base64Files.push({base64,file})} 30await new Promise(resolve=>setTimeout(resolve,0))}catch{lastError={title:"PDF Page Error",desc:`Page ${pageNum} could not be processed.`,type:"file-type"}}}}catch(error){console.error("PDF conversion error:",error);lastError={title:invalidFile,desc:"Upload a valid File",type:"file-type"}} 31if(lastError){showAlertBox(lastError.title,lastError.desc,lastError.type)} 32return base64Files};export const base64CheckImageExists=(base64Data,callback)=>{if(/^data:image\/(heif)/i.test(base64Data)||base64Data.startsWith("data:application/octet-stream")){callback(!0);return} 33const img=new Image();img.onload=()=>callback(!0);img.onerror=()=>callback(!1);img.src=base64Data};export const imageUrlToFileList=async(imageUrl)=>{const fileList=new DataTransfer();try{const response=await fetch(imageUrl);if(!response.ok)throw new Error("Fetch failed");const blob=await response.blob();const file=new File([blob],`image.${blob.type.split("/").pop()}`,{type:blob.type});fileList.items.add(file)}catch{const formData=new FormData();const csrfToken=$('meta[name="_token"]').attr('content');formData.append('imageUrl',imageUrl);formData.append('_token',csrfToken);try{const blob=await new Promise((resolve,reject)=>{$.ajax({url:'/fetch-file',method:'POST',data:formData,processData:!1,contentType:!1,xhrFields:{responseType:'blob'},success:resolve,error:reject})});const file=new File([blob],`image.${blob.type.split("/").pop()}`,{type:blob.type});fileList.items.add(file)}catch(ajaxError){throw new Error("Image fetch via AJAX failed")}} 34return[...fileList.files]};export const downloadTextFilesAsZip=async({selector=".text_response",filename="Extract-text-files.zip",singleFile=!1}={})=>{const texts=[];const readResponseEl=(el)=>{const node=el.get(0);if(node&&node.tagName==="TEXTAREA"){return{text:(el.val()||"").trim(),include:(el.val()||"").trim().length>0}} 35return{text:cleanText(el.html()),include:el.attr("contenteditable")==="true"}};if(singleFile){const el=$(selector).first();const{text,include}=readResponseEl(el);if(include&&text)texts.push(text);}else{$(selector).each(function(){const{text,include}=readResponseEl($(this));const fileName=$(this).closest(".processed-img").find(".file-name").text().split(".")[0];if(include&&text)texts.push([text,fileName]);})} 36if(!texts.length)return;if(singleFile){const blob=new Blob([texts.join("\n\n")],{type:"text/plain"});const fileName=filename!==""?filename+".txt":"text-file.txt";$("<a>").attr("href",URL.createObjectURL(blob)).attr("download",fileName).appendTo("body")[0].click()}else{await loadScript(scriptToRequire.zip.src,scriptToRequire.zip.id);const zip=new JSZip();
36texts.forEach(([text,fileName],i)=>{if(text)zip.file(`${i + 1}_${fileName}.txt`,text);});zip.generateAsync({type:"blob"}).then(blob=>{$("<a>").attr("href",URL.createObjectURL(blob)).attr("download",filename).appendTo("body")[0].click()})}};const cleanText=html=>(html||'').replace(/<br\s*\/?>/gi,'\n').replace(/<\/(h[1-6]|p|div)>/gi,'\n\n').replace(/<[^>]+>/g,'').replace(/ /g,' ').replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/[\u200B-\u200D\uFEFF]/g,'').trim();export const downloadImagesFilesZip=async({selector=".image-main .converted-img",filename="images.zip",singleFile=!1,containerIndex=null,groupByFolder=!1,folderSelector=".image-container",imageNamer=null}={})=>{try{await loadScript(scriptToRequire.zip.src,scriptToRequire.zip.id);await loadScript(scriptToRequire.fileSaver.src,scriptToRequire.fileSaver.id);const zip=new JSZip();const tasks=[];const addImageToZip=(target,src,name)=>{if(!src)return;if(src.startsWith("data:image/")){const base64Data=src.split(",")[1];if(base64Data)target.file(name,base64Data,{base64:!0})}else if(src.startsWith("blob:")){tasks.push(fetch(src).then(res=>res.blob()).then(blob=>blob.arrayBuffer()).then(buffer=>target.file(name,buffer)).catch(err=>console.error("Blob fetch error:",err)))}else{console.warn("Unsupported image source:",src)}};const sanitizeSourceName=(name)=>(name||"").replace(/\.[^.]+$/,"").replace(/[\/\\:*?"<>|]/g,"-").trim();const getSourceName=(el)=>sanitizeSourceName($(el).closest(".process-item, .processed-img").find(".file-name").first().text().trim());const buildImageName=(i,sourceName)=>typeof imageNamer==="function"?imageNamer(i,sourceName):`image-${i + 1}.jpg`;if(groupByFolder&&!(singleFile&&containerIndex!==null)){const containers=$(folderSelector).filter((i,el)=>$(el).find(selector).length>0);if(!containers.length){console.warn("No images found to download.");return} 37const usedNames={};containers.each((cIndex,container)=>{const rawName=$(container).closest(".process-item, .processed-img").find(".file-name").first().text().trim();let folderName=(rawName?rawName.replace(/\.[^.]+$/,""):"").replace(/[\/:*?"<>|]/g,"-").trim()||`file-${cIndex + 1}`;usedNames[folderName]=(usedNames[folderName]||0)+1;if(usedNames[folderName]>1)folderName=`${folderName}-${usedNames[folderName]}`;const folder=zip.folder(folderName);const sourceName=sanitizeSourceName(rawName);$(container).find(selector).each((i,el)=>{addImageToZip(folder,el.src,buildImageName(i,sourceName))})})}else{let images;if(singleFile&&containerIndex!==null){images=$(`#image-container-${containerIndex} ${selector}`)}else{images=$(selector)} 38if(!images.length){console.warn("No images found to download.");return} 39images.each((i,el)=>{addImageToZip(zip,el.src,buildImageName(i,getSourceName(el)))})} 40await Promise.all(tasks);const zipBlob=await zip.generateAsync({type:"blob"});saveAs(zipBlob,filename)}catch(err){console.error("Error in downloadImagesFilesZip:",err)}}
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.