scripts / download-languages.js
"use strict";
// Downloads the Tesseract language data files needed by the OCR parser.
// Both files are fetched from the naptha/tessdata repository (the source used
// by tesseract.js) and saved into the project root so they ship with the repo
// and tesseract.js never has to download them from the network on first OCR.
//
// npm run download
//
// Uses the "_fast" builds to match what tesseract.js fetches by default.
const fs = require("node:fs");
const path = require("node:path");
const https = require("node:https");
const { pipeline } = require("node:stream/promises");
const { createGunzip } = require("node:zlib");
const projectRoot = path.resolve(__dirname, "..");
// tesseract.js language code -> URL of the .traineddata.gz in naptha/tessdata
// (the repo's data files live on the gh-pages branch)
const ASSETS = {
eng: "https://raw.githubusercontent.com/naptha/tessdata/gh-pages/4.0.0_fast/eng.traineddata.gz",
rus: "https://raw.githubusercontent.com/naptha/tessdata/gh-pages/4.0.0_fast/rus.traineddata.gz",
};
async function download(url, dest) {
try {
const res = await new Promise((resolve, reject) => {
https
.get(url, resolve)
.on("error", reject);
});
if (res.statusCode !== 200) {
res.resume();
throw new Error(`HTTP ${res.statusCode} for ${url}`);
}
const file = fs.createWriteStream(dest);
await pipeline(res, file);
} catch (err) {
fs.rmSync(dest, { force: true });
throw err;
}
}
async function main() {
const haveAny = Object.values(ASSETS).length > 0;
if (!haveAny) return;
let hadError = false;
for (const [lang, url] of Object.entries(ASSETS)) {
const gz = path.join(projectRoot, `${lang}.traineddata.gz`);
const dest = path.join(projectRoot, `${lang}.traineddata`);
console.log(`[download-languages] Downloading ${lang}...`);
try {
await download(url, gz);
await pipeline(
fs.createReadStream(gz),
createGunzip(),
fs.createWriteStream(dest),
);
fs.unlinkSync(gz);
console.log(`[download-languages] Saved ${dest}`);
} catch (err) {
hadError = true;
console.error(`[download-languages] Failed to download ${lang}:`, err.message);
}
}
if (hadError) {
console.error("[download-languages] One or more language files failed to download.");
process.exitCode = 1;
} else {
console.log("[download-languages] All language files are up to date.");
}
}
void main();scripts / download-languages.js
"use strict";
// Downloads the Tesseract language data files needed by the OCR parser.
// Both files are fetched from the naptha/tessdata repository (the source used
// by tesseract.js) and saved into the project root so they ship with the repo
// and tesseract.js never has to download them from the network on first OCR.
//
// npm run download
//
// Uses the "_fast" builds to match what tesseract.js fetches by default.
const fs = require("node:fs");
const path = require("node:path");
const https = require("node:https");
const { pipeline } = require("node:stream/promises");
const { createGunzip } = require("node:zlib");
const projectRoot = path.resolve(__dirname, "..");
// tesseract.js language code -> URL of the .traineddata.gz in naptha/tessdata
// (the repo's data files live on the gh-pages branch)
const ASSETS = {
eng: "https://raw.githubusercontent.com/naptha/tessdata/gh-pages/4.0.0_fast/eng.traineddata.gz",
rus: "https://raw.githubusercontent.com/naptha/tessdata/gh-pages/4.0.0_fast/rus.traineddata.gz",
};
async function download(url, dest) {
try {
const res = await new Promise((resolve, reject) => {
https
.get(url, resolve)
.on("error", reject);
});
if (res.statusCode !== 200) {
res.resume();
throw new Error(`HTTP ${res.statusCode} for ${url}`);
}
const file = fs.createWriteStream(dest);
await pipeline(res, file);
} catch (err) {
fs.rmSync(dest, { force: true });
throw err;
}
}
async function main() {
const haveAny = Object.values(ASSETS).length > 0;
if (!haveAny) return;
let hadError = false;
for (const [lang, url] of Object.entries(ASSETS)) {
const gz = path.join(projectRoot, `${lang}.traineddata.gz`);
const dest = path.join(projectRoot, `${lang}.traineddata`);
console.log(`[download-languages] Downloading ${lang}...`);
try {
await download(url, gz);
await pipeline(
fs.createReadStream(gz),
createGunzip(),
fs.createWriteStream(dest),
);
fs.unlinkSync(gz);
console.log(`[download-languages] Saved ${dest}`);
} catch (err) {
hadError = true;
console.error(`[download-languages] Failed to download ${lang}:`, err.message);
}
}
if (hadError) {
console.error("[download-languages] One or more language files failed to download.");
process.exitCode = 1;
} else {
console.log("[download-languages] All language files are up to date.");
}
}
void main();