{"version":3,"sources":["../src/index.ts","../src/functions.ts","../src/convert.ts"],"sourcesContent":["export { classifyDocument } from './functions';\nexport type { documentDictionary } from './types';\n\n\n","import { stringSimilarity } from \"string-similarity-js\";\nimport * as Tesseract from \"tesseract.js\";\nimport type { documentDictionary } from \"./types\";\nimport { convert } from \"./convert\";\n\nexport function findTargetWords(\n  documentText: string,\n  targetWords: string[],\n  threshold: number = 0.75\n): string[] {\n  const foundTargetWords: string[] = [];\n  const documentWords = documentText.split(/\\s+/);\n\n  documentWords.forEach((docWord) => {\n    targetWords.forEach((targetWord) => {\n      const similarity = stringSimilarity(\n        docWord.toLowerCase(),\n        targetWord.toLowerCase()\n      );\n      if (similarity >= threshold) {\n        foundTargetWords.push(targetWord);\n      }\n    });\n  });\n\n  return foundTargetWords;\n}\n\nconst defaultDocumentDictionary: documentDictionary = {\n  Militærbevis: [\n    [\"førstegangstjeneste\", \"bevis\", \"avtjent\"],\n    [\"attest\", \"førstegangstjeneste\"],\n    [\"fullført\", \"førstegangstjeneste\"],\n  ],\n  Politiattest: [[\"politiattest\", \"politidistrikt\"], [\"police certificate\"]],\n  Kompetansebevis: [[\"omfatter\", \"opplæring\", \"utdanningsprogram\"]],\n  Legeerklæring: [[\"legeerklæring\", \"fødselsnummer\"]],\n  Bostedsattest: [\n    [\"registrerte\", \"opplysninger\", \"folkeregisteret\"],\n    [\"bostedsattest\", \"bostedsadresse\", \"registrert\"],\n    [\"registrert\", \"adressehistorikk\", \"folkeregisteret\"],\n  ],\n};\n\ntype ClassifyDocumentOptions = {\n  onProgress?: (progress: number) => void;\n  customDocumentDictionary?: documentDictionary;\n  maxNumPages?: number;\n};\n\nexport async function classifyDocument(\n  file: File,\n  options: ClassifyDocumentOptions = {}\n): Promise<{ classification: string; text: string }> {\n  const {\n    onProgress,\n    customDocumentDictionary,\n    maxNumPages = Infinity, // Default value if not provided\n  } = options;\n\n  // Merge the default dictionary with a custom one, if provided\n  const documentDictionary = {\n    ...defaultDocumentDictionary,\n    ...customDocumentDictionary,\n  };\n\n  let BlobArray: Blob[] = [];\n\n  if (file.type === \"application/pdf\") {\n    const pdfPath = URL.createObjectURL(file);\n    BlobArray = await convert(pdfPath, maxNumPages);\n    console.log(\"Blob to read set by convert function\");\n  } else if (file.type.startsWith(\"image/\")) {\n    // Check for image type explicitly\n    BlobArray.push(file);\n  } else {\n    throw new Error(\"Unsupported file type. Please provide a PDF or an image.\");\n  }\n\n  let progress = 0;\n  const totalBlobs = Math.min(BlobArray.length, maxNumPages);\n  let fullText = \"\";\n  const targetWords = Array.from(\n    new Set(Object.values(documentDictionary).flat(2))\n  );\n  try {\n    for (let i = 0; i < totalBlobs; i++) {\n      const text = await ocrBlob(BlobArray[i]);\n      fullText += text;\n      progress = Math.round(((i + 1) / totalBlobs) * 100);\n      if (onProgress) {\n        onProgress(progress);\n      }\n\n      const targetWordsFound = findTargetWords(text, targetWords);\n      const classification = determineClassification(\n        targetWordsFound,\n        documentDictionary\n      );\n      if (classification !== \"Ukjent\") {\n        return { classification, text: fullText };\n      }\n    }\n  } catch (error) {\n    console.log(\"Error in ocr process: \", error);\n  }\n\n  return { classification: \"Ukjent\", text: fullText };\n}\n\nfunction determineClassification(\n  targetWordsFound: string[],\n  documentDictionary: documentDictionary\n): string {\n  for (const [classification, targetWordSets] of Object.entries(\n    documentDictionary\n  )) {\n    for (const targetWords of targetWordSets) {\n      if (targetWords.every((word) => targetWordsFound.includes(word))) {\n        return classification;\n      }\n    }\n  }\n  return \"Ukjent\";\n}\n\nasync function ocrBlob(\n  blob: Blob,\n  onProgress?: (progress: number) => void\n): Promise<string> {\n  const reader = new FileReader();\n  const worker = await Tesseract.createWorker([\"nor\", \"eng\"], 1, {\n    logger: (m) => {\n      if (m.status === \"recognizing text\" && onProgress) {\n        onProgress(m.progress * 100);\n      }\n    },\n  });\n  await worker.setParameters({\n    tessedit_pageseg_mode: Tesseract.PSM.AUTO_OSD,\n  });\n  return new Promise((resolve, reject) => {\n    reader.onload = async () => {\n      const imageDataUrl = reader.result as string;\n      try {\n        const {\n          data: { text },\n        } = await worker.recognize(imageDataUrl, {\n          rotateAuto: true,\n        });\n        resolve(text);\n      } catch (err) {\n        console.error(err);\n        reject(err);\n      }\n    };\n    reader.readAsDataURL(blob);\n  });\n}\n","import * as pdfjsLib from \"pdfjs-dist\";\n\npdfjsLib.GlobalWorkerOptions.workerSrc =\n  \"https://cdn.jsdelivr.net/npm/pdfjs-dist@4.4.168/build/pdf.worker.min.mjs\";\n\nexport async function convert(pdfPath: string, maxNumPages: number): Promise<Blob[]> {\n  try {\n    const loadingTask = pdfjsLib.getDocument(pdfPath);\n    const doc = await loadingTask.promise;\n    const totalPages = Math.min(doc.numPages, maxNumPages);\n    let blobArray: Blob[] = [];\n\n    for (let i = 1; i <= totalPages; i++) {\n      const page = await doc.getPage(i);\n      const viewport = page.getViewport({ scale: 1.5 });\n\n      const canvas = document.createElement(\"canvas\");\n      const context = canvas.getContext(\"2d\");\n\n      if (!context) {\n        throw new Error(\"Failed to get canvas context\");\n      }\n\n      canvas.height = viewport.height;\n      canvas.width = viewport.width;\n\n      const renderContext = {\n        canvasContext: context,\n        viewport: viewport,\n      };\n\n      await page.render(renderContext).promise;\n\n      // Convert the canvas to a Blob\n      const blob = await new Promise<Blob>((resolve, reject) => {\n        canvas.toBlob(\n          (blob) => {\n            if (blob) {\n              console.log(\"Converted PDF to Blob!\");\n              resolve(blob);\n            } else {\n              reject(new Error(\"Failed to convert canvas to blob\"));\n            }\n          },\n          \"image/png\",\n          1\n        ); // Adjust image quality parameter (third argument)\n      });\n\n      blobArray.push(blob);\n    }\n\n    return blobArray;\n  } catch (error) {\n    console.error(\"Failed to load or process PDF:\", error);\n    throw error; // Throw the error so the caller knows the conversion failed\n  }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,kCAAiC;AACjC,gBAA2B;;;ACD3B,eAA0B;AAEjB,6BAAoB,YAC3B;AAEF,eAAsB,QAAQ,SAAiB,aAAsC;AACnF,MAAI;AACF,UAAM,cAAuB,qBAAY,OAAO;AAChD,UAAM,MAAM,MAAM,YAAY;AAC9B,UAAM,aAAa,KAAK,IAAI,IAAI,UAAU,WAAW;AACrD,QAAI,YAAoB,CAAC;AAEzB,aAAS,IAAI,GAAG,KAAK,YAAY,KAAK;AACpC,YAAM,OAAO,MAAM,IAAI,QAAQ,CAAC;AAChC,YAAM,WAAW,KAAK,YAAY,EAAE,OAAO,IAAI,CAAC;AAEhD,YAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,YAAM,UAAU,OAAO,WAAW,IAAI;AAEtC,UAAI,CAAC,SAAS;AACZ,cAAM,IAAI,MAAM,8BAA8B;AAAA,MAChD;AAEA,aAAO,SAAS,SAAS;AACzB,aAAO,QAAQ,SAAS;AAExB,YAAM,gBAAgB;AAAA,QACpB,eAAe;AAAA,QACf;AAAA,MACF;AAEA,YAAM,KAAK,OAAO,aAAa,EAAE;AAGjC,YAAM,OAAO,MAAM,IAAI,QAAc,CAAC,SAAS,WAAW;AACxD,eAAO;AAAA,UACL,CAACA,UAAS;AACR,gBAAIA,OAAM;AACR,sBAAQ,IAAI,wBAAwB;AACpC,sBAAQA,KAAI;AAAA,YACd,OAAO;AACL,qBAAO,IAAI,MAAM,kCAAkC,CAAC;AAAA,YACtD;AAAA,UACF;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF,CAAC;AAED,gBAAU,KAAK,IAAI;AAAA,IACrB;AAEA,WAAO;AAAA,EACT,SAAS,OAAO;AACd,YAAQ,MAAM,kCAAkC,KAAK;AACrD,UAAM;AAAA,EACR;AACF;;;ADpDO,SAAS,gBACd,cACA,aACA,YAAoB,MACV;AACV,QAAM,mBAA6B,CAAC;AACpC,QAAM,gBAAgB,aAAa,MAAM,KAAK;AAE9C,gBAAc,QAAQ,CAAC,YAAY;AACjC,gBAAY,QAAQ,CAAC,eAAe;AAClC,YAAM,iBAAa;AAAA,QACjB,QAAQ,YAAY;AAAA,QACpB,WAAW,YAAY;AAAA,MACzB;AACA,UAAI,cAAc,WAAW;AAC3B,yBAAiB,KAAK,UAAU;AAAA,MAClC;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AAED,SAAO;AACT;AAEA,IAAM,4BAAgD;AAAA,EACpD,mBAAc;AAAA,IACZ,CAAC,0BAAuB,SAAS,SAAS;AAAA,IAC1C,CAAC,UAAU,wBAAqB;AAAA,IAChC,CAAC,eAAY,wBAAqB;AAAA,EACpC;AAAA,EACA,cAAc,CAAC,CAAC,gBAAgB,gBAAgB,GAAG,CAAC,oBAAoB,CAAC;AAAA,EACzE,iBAAiB,CAAC,CAAC,YAAY,gBAAa,mBAAmB,CAAC;AAAA,EAChE,oBAAe,CAAC,CAAC,oBAAiB,kBAAe,CAAC;AAAA,EAClD,eAAe;AAAA,IACb,CAAC,eAAe,gBAAgB,iBAAiB;AAAA,IACjD,CAAC,iBAAiB,kBAAkB,YAAY;AAAA,IAChD,CAAC,cAAc,oBAAoB,iBAAiB;AAAA,EACtD;AACF;AAQA,eAAsB,iBACpB,MACA,UAAmC,CAAC,GACe;AACnD,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA,cAAc;AAAA;AAAA,EAChB,IAAI;AAGJ,QAAM,qBAAqB;AAAA,IACzB,GAAG;AAAA,IACH,GAAG;AAAA,EACL;AAEA,MAAI,YAAoB,CAAC;AAEzB,MAAI,KAAK,SAAS,mBAAmB;AACnC,UAAM,UAAU,IAAI,gBAAgB,IAAI;AACxC,gBAAY,MAAM,QAAQ,SAAS,WAAW;AAC9C,YAAQ,IAAI,sCAAsC;AAAA,EACpD,WAAW,KAAK,KAAK,WAAW,QAAQ,GAAG;AAEzC,cAAU,KAAK,IAAI;AAAA,EACrB,OAAO;AACL,UAAM,IAAI,MAAM,0DAA0D;AAAA,EAC5E;AAEA,MAAI,WAAW;AACf,QAAM,aAAa,KAAK,IAAI,UAAU,QAAQ,WAAW;AACzD,MAAI,WAAW;AACf,QAAM,cAAc,MAAM;AAAA,IACxB,IAAI,IAAI,OAAO,OAAO,kBAAkB,EAAE,KAAK,CAAC,CAAC;AAAA,EACnD;AACA,MAAI;AACF,aAAS,IAAI,GAAG,IAAI,YAAY,KAAK;AACnC,YAAM,OAAO,MAAM,QAAQ,UAAU,CAAC,CAAC;AACvC,kBAAY;AACZ,iBAAW,KAAK,OAAQ,IAAI,KAAK,aAAc,GAAG;AAClD,UAAI,YAAY;AACd,mBAAW,QAAQ;AAAA,MACrB;AAEA,YAAM,mBAAmB,gBAAgB,MAAM,WAAW;AAC1D,YAAM,iBAAiB;AAAA,QACrB;AAAA,QACA;AAAA,MACF;AACA,UAAI,mBAAmB,UAAU;AAC/B,eAAO,EAAE,gBAAgB,MAAM,SAAS;AAAA,MAC1C;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,IAAI,0BAA0B,KAAK;AAAA,EAC7C;AAEA,SAAO,EAAE,gBAAgB,UAAU,MAAM,SAAS;AACpD;AAEA,SAAS,wBACP,kBACA,oBACQ;AACR,aAAW,CAAC,gBAAgB,cAAc,KAAK,OAAO;AAAA,IACpD;AAAA,EACF,GAAG;AACD,eAAW,eAAe,gBAAgB;AACxC,UAAI,YAAY,MAAM,CAAC,SAAS,iBAAiB,SAAS,IAAI,CAAC,GAAG;AAChE,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEA,eAAe,QACb,MACA,YACiB;AACjB,QAAM,SAAS,IAAI,WAAW;AAC9B,QAAM,SAAS,MAAgB,uBAAa,CAAC,OAAO,KAAK,GAAG,GAAG;AAAA,IAC7D,QAAQ,CAAC,MAAM;AACb,UAAI,EAAE,WAAW,sBAAsB,YAAY;AACjD,mBAAW,EAAE,WAAW,GAAG;AAAA,MAC7B;AAAA,IACF;AAAA,EACF,CAAC;AACD,QAAM,OAAO,cAAc;AAAA,IACzB,uBAAiC,cAAI;AAAA,EACvC,CAAC;AACD,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,WAAO,SAAS,YAAY;AAC1B,YAAM,eAAe,OAAO;AAC5B,UAAI;AACF,cAAM;AAAA,UACJ,MAAM,EAAE,KAAK;AAAA,QACf,IAAI,MAAM,OAAO,UAAU,cAAc;AAAA,UACvC,YAAY;AAAA,QACd,CAAC;AACD,gBAAQ,IAAI;AAAA,MACd,SAAS,KAAK;AACZ,gBAAQ,MAAM,GAAG;AACjB,eAAO,GAAG;AAAA,MACZ;AAAA,IACF;AACA,WAAO,cAAc,IAAI;AAAA,EAC3B,CAAC;AACH;","names":["blob"]}