From 15fdd9e3aca39b8a14c0234e450f8cb010d36b64 Mon Sep 17 00:00:00 2001
From: Balearica <admin@scribeocr.com>
Date: Wed, 17 May 2023 16:51:49 -0700
Subject: [PATCH 1/7] Added Node.js v18 and v20 to Actions (#765)

---
 .github/workflows/node.js.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml
index 3176ee9f..5df19058 100644
--- a/.github/workflows/node.js.yml
+++ b/.github/workflows/node.js.yml
@@ -16,7 +16,7 @@ jobs:
 
     strategy:
       matrix:
-        node-version: [14.x, 16.x]
+        node-version: [14.x, 16.x, 18.x, 20.x]
 
     steps:
     - uses: actions/checkout@v3

From 6437f2870461bc27e3c744af9cb6d8090d9b9144 Mon Sep 17 00:00:00 2001
From: Balearica <admin@scribeocr.com>
Date: Mon, 29 May 2023 11:40:45 -0700
Subject: [PATCH 2/7] Add ability to analyse layout without running recognition
 (#770)

---
 src/index.d.ts                               |  1 +
 src/worker-script/constants/defaultOutput.js |  2 ++
 src/worker-script/index.js                   | 14 +++++---
 src/worker-script/utils/dump.js              | 38 +++++++++++---------
 4 files changed, 33 insertions(+), 22 deletions(-)

diff --git a/src/index.d.ts b/src/index.d.ts
index 2a01a751..8b810e08 100644
--- a/src/index.d.ts
+++ b/src/index.d.ts
@@ -70,6 +70,7 @@ declare namespace Tesseract {
   interface OutputFormats {
     text: boolean;
     blocks: boolean;
+    layoutBlocks: boolean;
     hocr: boolean;
     tsv: boolean;
     box: boolean;
diff --git a/src/worker-script/constants/defaultOutput.js b/src/worker-script/constants/defaultOutput.js
index b184e17b..0c16697b 100644
--- a/src/worker-script/constants/defaultOutput.js
+++ b/src/worker-script/constants/defaultOutput.js
@@ -5,6 +5,7 @@
 module.exports = {
   text: true,
   blocks: true,
+  layoutBlocks: false,
   hocr: true,
   tsv: true,
   box: false,
@@ -14,4 +15,5 @@ module.exports = {
   imageColor: false,
   imageGrey: false,
   imageBinary: false,
+  debug: false,
 };
diff --git a/src/worker-script/index.js b/src/worker-script/index.js
index 9f234099..30e701fb 100644
--- a/src/worker-script/index.js
+++ b/src/worker-script/index.js
@@ -255,7 +255,7 @@ const processOutput = (output) => {
   if (params.tessjs_create_tsv === '1') workingOutput.tsv = true;
   if (params.tessjs_create_unlv === '1') workingOutput.unlv = true;
 
-  const nonRecOutputs = ['imageColor', 'imageGrey', 'imageBinary'];
+  const nonRecOutputs = ['imageColor', 'imageGrey', 'imageBinary', 'layoutBlocks'];
   let recOutputCount = 0;
   for (const prop of Object.keys(output)) {
     workingOutput[prop] = output[prop];
@@ -267,7 +267,8 @@ const processOutput = (output) => {
       }
     }
   }
-  return { workingOutput, recOutputCount };
+  const skipRecognition = recOutputCount === 0;
+  return { workingOutput, skipRecognition };
 };
 
 // List of options for Tesseract.js (rather than passed through to Tesseract),
@@ -302,7 +303,7 @@ const recognize = async ({
       }
     }
 
-    const { workingOutput, recOutputCount } = processOutput(output);
+    const { workingOutput, skipRecognition } = processOutput(output);
 
     // When the auto-rotate option is True, setImage is called with no angle,
     // then the angle is calculated by Tesseract and then setImage is re-called.
@@ -352,14 +353,17 @@ const recognize = async ({
       api.SetRectangle(rec.left, rec.top, rec.width, rec.height);
     }
 
-    if (recOutputCount > 0) {
+    if (!skipRecognition) {
       api.Recognize(null);
     } else {
+      if (output.layoutBlocks) {
+        api.AnalyseLayout();
+      }
       log('Skipping recognition: all output options requiring recognition are disabled.');
     }
     const { pdfTitle } = options;
     const { pdfTextOnly } = options;
-    const result = dump(TessModule, api, workingOutput, { pdfTitle, pdfTextOnly });
+    const result = dump(TessModule, api, workingOutput, { pdfTitle, pdfTextOnly, skipRecognition });
     result.rotateRadians = rotateRadiansFinal;
 
     if (output.debug) TessModule.FS.unlink('/debugInternal.txt');
diff --git a/src/worker-script/utils/dump.js b/src/worker-script/utils/dump.js
index 7edf31c3..9c4d3a18 100644
--- a/src/worker-script/utils/dump.js
+++ b/src/worker-script/utils/dump.js
@@ -79,7 +79,10 @@ module.exports = (TessModule, api, output, options) => {
     return TessModule.FS.readFile('/tesseract-ocr.pdf');
   };
 
-  if (output.blocks) {
+  // If output.layoutBlocks is true and options.skipRecognition is true,
+  // the user wants layout data but text recognition has not been run.
+  // In this case, fields that require text recognition are skipped.
+  if (output.blocks || output.layoutBlocks) {
     ri.Begin();
     do {
       if (ri.IsAtBeginningOf(RIL_BLOCK)) {
@@ -102,8 +105,8 @@ module.exports = (TessModule, api, output, options) => {
 
         block = {
           paragraphs: [],
-          text: ri.GetUTF8Text(RIL_BLOCK),
-          confidence: ri.Confidence(RIL_BLOCK),
+          text: !options.skipRecognition ? ri.GetUTF8Text(RIL_BLOCK) : null,
+          confidence: !options.skipRecognition ? ri.Confidence(RIL_BLOCK) : null,
           baseline: ri.getBaseline(RIL_BLOCK),
           bbox: ri.getBoundingBox(RIL_BLOCK),
           blocktype: enumToString(ri.BlockType(), 'PT'),
@@ -114,8 +117,8 @@ module.exports = (TessModule, api, output, options) => {
       if (ri.IsAtBeginningOf(RIL_PARA)) {
         para = {
           lines: [],
-          text: ri.GetUTF8Text(RIL_PARA),
-          confidence: ri.Confidence(RIL_PARA),
+          text: !options.skipRecognition ? ri.GetUTF8Text(RIL_PARA) : null,
+          confidence: !options.skipRecognition ? ri.Confidence(RIL_PARA) : null,
           baseline: ri.getBaseline(RIL_PARA),
           bbox: ri.getBoundingBox(RIL_PARA),
           is_ltr: !!ri.ParagraphIsLtr(),
@@ -125,8 +128,8 @@ module.exports = (TessModule, api, output, options) => {
       if (ri.IsAtBeginningOf(RIL_TEXTLINE)) {
         textline = {
           words: [],
-          text: ri.GetUTF8Text(RIL_TEXTLINE),
-          confidence: ri.Confidence(RIL_TEXTLINE),
+          text: !options.skipRecognition ? ri.GetUTF8Text(RIL_TEXTLINE) : null,
+          confidence: !options.skipRecognition ? ri.Confidence(RIL_TEXTLINE) : null,
           baseline: ri.getBaseline(RIL_TEXTLINE),
           bbox: ri.getBoundingBox(RIL_TEXTLINE),
         };
@@ -139,8 +142,8 @@ module.exports = (TessModule, api, output, options) => {
           symbols: [],
           choices: [],
 
-          text: ri.GetUTF8Text(RIL_WORD),
-          confidence: ri.Confidence(RIL_WORD),
+          text: !options.skipRecognition ? ri.GetUTF8Text(RIL_WORD) : null,
+          confidence: !options.skipRecognition ? ri.Confidence(RIL_WORD) : null,
           baseline: ri.getBaseline(RIL_WORD),
           bbox: ri.getBoundingBox(RIL_WORD),
 
@@ -162,8 +165,8 @@ module.exports = (TessModule, api, output, options) => {
         const wc = new TessModule.WordChoiceIterator(ri);
         do {
           word.choices.push({
-            text: wc.GetUTF8Text(),
-            confidence: wc.Confidence(),
+            text: !options.skipRecognition ? wc.GetUTF8Text() : null,
+            confidence: !options.skipRecognition ? wc.Confidence() : null,
           });
         } while (wc.Next());
         TessModule.destroy(wc);
@@ -179,8 +182,8 @@ module.exports = (TessModule, api, output, options) => {
         symbol = {
           choices: [],
           image: null,
-          text: ri.GetUTF8Text(RIL_SYMBOL),
-          confidence: ri.Confidence(RIL_SYMBOL),
+          text: !options.skipRecognition ? ri.GetUTF8Text(RIL_SYMBOL) : null,
+          confidence: !options.skipRecognition ? ri.Confidence(RIL_SYMBOL) : null,
           baseline: ri.getBaseline(RIL_SYMBOL),
           bbox: ri.getBoundingBox(RIL_SYMBOL),
           is_superscript: !!ri.SymbolIsSuperscript(),
@@ -191,8 +194,8 @@ module.exports = (TessModule, api, output, options) => {
         const ci = new TessModule.ChoiceIterator(ri);
         do {
           symbol.choices.push({
-            text: ci.GetUTF8Text(),
-            confidence: ci.Confidence(),
+            text: !options.skipRecognition ? ci.GetUTF8Text() : null,
+            confidence: !options.skipRecognition ? ci.Confidence() : null,
           });
         } while (ci.Next());
         // TessModule.destroy(i);
@@ -212,8 +215,9 @@ module.exports = (TessModule, api, output, options) => {
     imageColor: output.imageColor ? getImage(imageType.COLOR) : null,
     imageGrey: output.imageGrey ? getImage(imageType.GREY) : null,
     imageBinary: output.imageBinary ? getImage(imageType.BINARY) : null,
-    confidence: api.MeanTextConf(),
-    blocks: output.blocks ? blocks : null,
+    confidence: !options.skipRecognition ? api.MeanTextConf() : null,
+    blocks: output.blocks && !options.skipRecognition ? blocks : null,
+    layoutBlocks: output.layoutBlocks && options.skipRecognition ? blocks : null,
     psm: enumToString(api.GetPageSegMode(), 'PSM'),
     oem: enumToString(api.oem(), 'OEM'),
     version: api.Version(),

From a5f10d843878c979530ce48e7978948aeff0a3b1 Mon Sep 17 00:00:00 2001
From: Nathan Babcock <nathan.r.babcock@gmail.com>
Date: Mon, 29 May 2023 23:30:07 -0500
Subject: [PATCH 3/7] Support `OffscreenCanvas` in browser version (#766)

---
 src/index.d.ts                  |  2 +-
 src/worker/browser/loadImage.js |  5 ++++-
 tests/recognize.test.js         | 32 ++++++++++++++++++++++++++++++++
 3 files changed, 37 insertions(+), 2 deletions(-)

diff --git a/src/index.d.ts b/src/index.d.ts
index 8b810e08..d4404b32 100644
--- a/src/index.d.ts
+++ b/src/index.d.ts
@@ -146,7 +146,7 @@ declare namespace Tesseract {
     BINARY = 2
   }
   type ImageLike = string | HTMLImageElement | HTMLCanvasElement | HTMLVideoElement
-    | CanvasRenderingContext2D | File | Blob | ImageData | Buffer;
+    | CanvasRenderingContext2D | File | Blob | ImageData | Buffer | OffscreenCanvas;
   interface Block {
     paragraphs: Paragraph[];
     text: string;
diff --git a/src/worker/browser/loadImage.js b/src/worker/browser/loadImage.js
index 2223d4f7..cea39a2c 100644
--- a/src/worker/browser/loadImage.js
+++ b/src/worker/browser/loadImage.js
@@ -43,7 +43,7 @@ const loadImage = async (image) => {
       const resp = await fetch(resolveURL(image));
       data = await resp.arrayBuffer();
     }
-  } else if (image instanceof HTMLElement) {
+  } else if (typeof HTMLElement !== 'undefined' && image instanceof HTMLElement) {
     if (image.tagName === 'IMG') {
       data = await loadImage(image.src);
     }
@@ -58,6 +58,9 @@ const loadImage = async (image) => {
         });
       });
     }
+  } else if (typeof OffscreenCanvas !== 'undefined' && image instanceof OffscreenCanvas) {
+    const blob = await image.convertToBlob();
+    data = await readFromBlobOrFile(blob);
   } else if (image instanceof File || image instanceof Blob) {
     data = await readFromBlobOrFile(image);
   }
diff --git a/tests/recognize.test.js b/tests/recognize.test.js
index 59ecd6f6..ca7ece4e 100644
--- a/tests/recognize.test.js
+++ b/tests/recognize.test.js
@@ -194,4 +194,36 @@ describe('recognize()', () => {
       }).timeout(TIMEOUT)
     ));
   });
+
+  (IS_BROWSER ? describe : describe.skip)('should read video from OffscreenCanvas (browser only)', () => {
+    // img tag is unable to render pbm, so let's skip it.
+    const formats = FORMATS.filter(f => f !== 'pbm');
+    let offscreenCanvas = null;
+    let imageDOM = null;
+    let idx = 0;
+    beforeEach((done) => {
+      imageDOM = document.createElement('img');
+      imageDOM.setAttribute('crossOrigin', 'Anonymous');
+      imageDOM.onload = () => {
+        offscreenCanvas = new OffscreenCanvas(imageDOM.width, imageDOM.height)
+        offscreenCanvas.getContext('2d').drawImage(imageDOM, 0, 0);
+        done();
+      };
+      imageDOM.setAttribute('src', `${IMAGE_PATH}/simple.${formats[idx]}`);
+      idx += 1;
+    });
+
+    afterEach(() => {
+      offscreenCanvas = null;
+      imageDOM.remove();
+    });
+
+    formats.forEach(format => (
+      it(`support ${format} format`, async () => {
+        await worker.initialize('eng');
+        const { data: { text } } = await worker.recognize(offscreenCanvas);
+        expect(text).to.be(SIMPLE_TEXT);
+      }).timeout(TIMEOUT)
+    ));
+  });
 });

From fd1c8b2dc72fa69be9fdcd6080c51ca17bb2bc4d Mon Sep 17 00:00:00 2001
From: Balearica <admin@scribeocr.com>
Date: Thu, 1 Jun 2023 22:39:56 -0700
Subject: [PATCH 4/7] Replaced resolve-url dependency per #773 (#774)

---
 package-lock.json                    | 12 ------------
 package.json                         |  1 -
 src/utils/resolvePaths.js            |  3 ++-
 src/worker/browser/defaultOptions.js |  2 +-
 src/worker/browser/loadImage.js      |  4 +---
 5 files changed, 4 insertions(+), 18 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index fa920387..1f4ee727 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -18,7 +18,6 @@
         "node-fetch": "^2.6.9",
         "opencollective-postinstall": "^2.0.3",
         "regenerator-runtime": "^0.13.3",
-        "resolve-url": "^0.2.1",
         "tesseract.js-core": "^4.0.4",
         "wasm-feature-detect": "^1.2.11",
         "zlibjs": "^0.3.1"
@@ -7798,12 +7797,6 @@
         "node": ">=4"
       }
     },
-    "node_modules/resolve-url": {
-      "version": "0.2.1",
-      "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
-      "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=",
-      "deprecated": "https://github.com/lydell/resolve-url#deprecated"
-    },
     "node_modules/rimraf": {
       "version": "5.0.0",
       "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.0.tgz",
@@ -15411,11 +15404,6 @@
       "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
       "dev": true
     },
-    "resolve-url": {
-      "version": "0.2.1",
-      "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
-      "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo="
-    },
     "rimraf": {
       "version": "5.0.0",
       "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.0.tgz",
diff --git a/package.json b/package.json
index 2a9963cc..0a4e59b2 100644
--- a/package.json
+++ b/package.json
@@ -70,7 +70,6 @@
     "node-fetch": "^2.6.9",
     "opencollective-postinstall": "^2.0.3",
     "regenerator-runtime": "^0.13.3",
-    "resolve-url": "^0.2.1",
     "tesseract.js-core": "^4.0.4",
     "wasm-feature-detect": "^1.2.11",
     "zlibjs": "^0.3.1"
diff --git a/src/utils/resolvePaths.js b/src/utils/resolvePaths.js
index 566d5785..19269655 100644
--- a/src/utils/resolvePaths.js
+++ b/src/utils/resolvePaths.js
@@ -1,5 +1,6 @@
 const isBrowser = require('./getEnvironment')('type') === 'browser';
-const resolveURL = isBrowser ? require('resolve-url') : s => s; // eslint-disable-line
+
+const resolveURL = isBrowser ? s => (new URL(s, window.location.href)).href : s => s; // eslint-disable-line
 
 module.exports = (options) => {
   const opts = { ...options };
diff --git a/src/worker/browser/defaultOptions.js b/src/worker/browser/defaultOptions.js
index 1c728cc6..feac58ff 100644
--- a/src/worker/browser/defaultOptions.js
+++ b/src/worker/browser/defaultOptions.js
@@ -1,4 +1,4 @@
-const resolveURL = require('resolve-url');
+const resolveURL = (s) => (new URL(s, window.location.href)).href;
 const { version } = require('../../../package.json');
 const defaultOptions = require('../../constants/defaultOptions');
 
diff --git a/src/worker/browser/loadImage.js b/src/worker/browser/loadImage.js
index cea39a2c..0b777c27 100644
--- a/src/worker/browser/loadImage.js
+++ b/src/worker/browser/loadImage.js
@@ -1,5 +1,3 @@
-const resolveURL = require('resolve-url');
-
 /**
  * readFromBlobOrFile
  *
@@ -40,7 +38,7 @@ const loadImage = async (image) => {
         .split('')
         .map((c) => c.charCodeAt(0));
     } else {
-      const resp = await fetch(resolveURL(image));
+      const resp = await fetch(image);
       data = await resp.arrayBuffer();
     }
   } else if (typeof HTMLElement !== 'undefined' && image instanceof HTMLElement) {

From 32acbd8579463bfdec4536dc0b83b3c28c56f48a Mon Sep 17 00:00:00 2001
From: Balearica <admin@scribeocr.com>
Date: Thu, 1 Jun 2023 23:32:04 -0700
Subject: [PATCH 5/7] Removed file-type dependency per #711 (#775)

---
 package-lock.json                   | 14 --------------
 package.json                        |  1 -
 src/worker-script/index.js          |  7 ++++---
 src/worker-script/utils/setImage.js |  6 +++---
 4 files changed, 7 insertions(+), 21 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index 1f4ee727..af7063c0 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11,7 +11,6 @@
       "license": "Apache-2.0",
       "dependencies": {
         "bmp-js": "^0.1.0",
-        "file-type": "^12.4.2",
         "idb-keyval": "^6.2.0",
         "is-electron": "^2.2.2",
         "is-url": "^1.2.4",
@@ -4576,14 +4575,6 @@
         "node": "^10.12.0 || >=12.0.0"
       }
     },
-    "node_modules/file-type": {
-      "version": "12.4.2",
-      "resolved": "https://registry.npmjs.org/file-type/-/file-type-12.4.2.tgz",
-      "integrity": "sha512-UssQP5ZgIOKelfsaB5CuGAL+Y+q7EmONuiwF3N5HAH0t27rvrttgi6Ra9k/+DVaY9UF6+ybxu5pOXLUdA8N7Vg==",
-      "engines": {
-        "node": ">=8"
-      }
-    },
     "node_modules/fill-range": {
       "version": "7.0.1",
       "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
@@ -13051,11 +13042,6 @@
         "flat-cache": "^3.0.4"
       }
     },
-    "file-type": {
-      "version": "12.4.2",
-      "resolved": "https://registry.npmjs.org/file-type/-/file-type-12.4.2.tgz",
-      "integrity": "sha512-UssQP5ZgIOKelfsaB5CuGAL+Y+q7EmONuiwF3N5HAH0t27rvrttgi6Ra9k/+DVaY9UF6+ybxu5pOXLUdA8N7Vg=="
-    },
     "fill-range": {
       "version": "7.0.1",
       "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
diff --git a/package.json b/package.json
index 0a4e59b2..fa327cda 100644
--- a/package.json
+++ b/package.json
@@ -63,7 +63,6 @@
   },
   "dependencies": {
     "bmp-js": "^0.1.0",
-    "file-type": "^12.4.2",
     "idb-keyval": "^6.2.0",
     "is-electron": "^2.2.2",
     "is-url": "^1.2.4",
diff --git a/src/worker-script/index.js b/src/worker-script/index.js
index 30e701fb..959589e5 100644
--- a/src/worker-script/index.js
+++ b/src/worker-script/index.js
@@ -8,7 +8,6 @@
  * @author Jerome Wu <jeromewus@gmail.com>
  */
 require('regenerator-runtime/runtime');
-const fileType = require('file-type');
 const isURL = require('is-url');
 const dump = require('./utils/dump');
 const isWebWorker = require('../utils/getEnvironment')('type') === 'webworker';
@@ -125,8 +124,10 @@ res) => {
 
     data = new Uint8Array(data);
 
-    const type = fileType(data);
-    if (typeof type !== 'undefined' && type.mime === 'application/gzip') {
+    // Check for gzip magic numbers (1F and 8B in hex)
+    const isGzip = (data[0] === 31 && data[1] === 139) || (data[1] === 31 && data[0] === 139);
+
+    if (isGzip) {
       data = adapter.gunzip(data);
     }
 
diff --git a/src/worker-script/utils/setImage.js b/src/worker-script/utils/setImage.js
index d9aec9b3..354521f1 100644
--- a/src/worker-script/utils/setImage.js
+++ b/src/worker-script/utils/setImage.js
@@ -1,5 +1,4 @@
 const bmp = require('bmp-js');
-const fileType = require('file-type');
 
 /**
  * setImage
@@ -9,7 +8,8 @@ const fileType = require('file-type');
  * @access public
  */
 module.exports = (TessModule, api, image, angle = 0) => {
-  const type = fileType(image);
+  // Check for bmp magic numbers (42 and 4D in hex)
+  const isBmp = (image[0] === 66 && image[1] === 77) || (image[1] === 66 && image[0] === 77);
 
   const exif = image.slice(0, 500).toString().match(/\x01\x12\x00\x03\x00\x00\x00\x01\x00(.)/)?.[1]?.charCodeAt(0) || 1;
 
@@ -18,7 +18,7 @@ module.exports = (TessModule, api, image, angle = 0) => {
   //  * @see https://github.com/DanBloomberg/leptonica/issues/607#issuecomment-1068802516
   //  * We therefore use bmp-js to convert all bmp files into a format Leptonica is known to support
   //  */
-  if (type && type.mime === 'image/bmp') {
+  if (isBmp) {
     // Not sure what this line actually does, but removing breaks the function
     const buf = Buffer.from(Array.from({ ...image, length: Object.keys(image).length }));
     const bmpBuf = bmp.decode(buf);

From 0d8e6fb6953d6d94acc6227c7be6b6e66b7f9637 Mon Sep 17 00:00:00 2001
From: Balearica <admin@scribeocr.com>
Date: Fri, 2 Jun 2023 17:40:54 -0700
Subject: [PATCH 6/7] Removed is-url check for browser version per #558 (#776)

---
 src/worker-script/index.js | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/src/worker-script/index.js b/src/worker-script/index.js
index 959589e5..9a2bc924 100644
--- a/src/worker-script/index.js
+++ b/src/worker-script/index.js
@@ -10,7 +10,7 @@
 require('regenerator-runtime/runtime');
 const isURL = require('is-url');
 const dump = require('./utils/dump');
-const isWebWorker = require('../utils/getEnvironment')('type') === 'webworker';
+const env = require('../utils/getEnvironment')('type');
 const setImage = require('./utils/setImage');
 const defaultParams = require('./constants/defaultParams');
 const defaultOutput = require('./constants/defaultOutput');
@@ -88,6 +88,8 @@ res) => {
     let data = null;
     let newData = false;
 
+    // Check for existing .traineddata file in cache
+    // This automatically fails if cacheMethod is set to 'refresh' or 'none'
     try {
       const _data = await readCache(`${cachePath || '.'}/${lang}.traineddata`);
       if (typeof _data !== 'undefined') {
@@ -97,23 +99,31 @@ res) => {
       } else {
         throw Error('Not found in cache');
       }
+    // Attempt to fetch new .traineddata file
     } catch (e) {
       newData = true;
       log(`[${workerId}]: Load ${lang}.traineddata from ${langPath}`);
       if (typeof _lang === 'string') {
         let path = null;
 
-        if (isURL(langPath) || langPath.startsWith('moz-extension://') || langPath.startsWith('chrome-extension://') || langPath.startsWith('file://')) { /** When langPath is an URL */
+        // For Node.js, langPath may be a URL or local file path
+        // The is-url package is used to tell the difference
+        // For the browser version, langPath is assumed to be a URL
+        if (env !== 'node' || isURL(langPath) || langPath.startsWith('moz-extension://') || langPath.startsWith('chrome-extension://') || langPath.startsWith('file://')) { /** When langPath is an URL */
           path = langPath.replace(/\/$/, '');
         }
 
+        // langPath is a URL, fetch from server
         if (path !== null) {
           const fetchUrl = `${path}/${lang}.traineddata${gzip ? '.gz' : ''}`;
-          const resp = await (isWebWorker ? fetch : adapter.fetch)(fetchUrl);
+          const resp = await (env === 'webworker' ? fetch : adapter.fetch)(fetchUrl);
           if (!resp.ok) {
             throw Error(`Network error while fetching ${fetchUrl}. Response code: ${resp.status}`);
           }
           data = await resp.arrayBuffer();
+
+        // langPath is a local file, read .traineddata from local filesystem
+        // (adapter.readCache is a generic file read function in Node.js version)
         } else {
           data = await adapter.readCache(`${langPath}/${lang}.traineddata${gzip ? '.gz' : ''}`);
         }

From 07feaa774d812fff99d04be9b132e222749fd51e Mon Sep 17 00:00:00 2001
From: Balearica <admin@scribeocr.com>
Date: Fri, 2 Jun 2023 17:46:59 -0700
Subject: [PATCH 7/7] 4.1.0

---
 package-lock.json | 4 ++--
 package.json      | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index af7063c0..2a721cff 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "tesseract.js",
-  "version": "4.0.6",
+  "version": "4.1.0",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
       "name": "tesseract.js",
-      "version": "4.0.6",
+      "version": "4.1.0",
       "hasInstallScript": true,
       "license": "Apache-2.0",
       "dependencies": {
diff --git a/package.json b/package.json
index fa327cda..d24ec80c 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "tesseract.js",
-  "version": "4.0.6",
+  "version": "4.1.0",
   "description": "Pure Javascript Multilingual OCR",
   "main": "src/index.js",
   "types": "src/index.d.ts",
