From 977e52b083d8e3daf017c7da61c8d54b6bcd37b9 Mon Sep 17 00:00:00 2001 From: eric8810 Date: Wed, 22 Jul 2026 22:43:41 +0800 Subject: [PATCH] =?UTF-8?q?fix(cli):=20=E5=AF=B8=E5=9F=9F=E9=87=8D?= =?UTF-8?q?=E6=98=8E=EF=BC=8C=E9=9B=B6=E7=95=8C=E5=8F=AF=E8=A1=8C=20=C2=B7?= =?UTF-8?q?=20restore=20CLI=20region=20handling?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allow the documented region option through native admission and accept zero-based x/y coordinates. Extend the existing package smoke with one real CLI ROI invocation, then bump the immutable release to 0.3.4. --- .github/workflows/npm-release.yml | 2 +- CHANGELOG.md | 7 +++++++ CMakeLists.txt | 2 +- bindings/node/bin/light-ocr.cjs | 2 +- bindings/node/package.json | 2 +- bindings/node/src/addon.cpp | 6 +++--- tools/npm/smoke.cjs | 23 +++++++++++++++++++++++ 7 files changed, 37 insertions(+), 7 deletions(-) diff --git a/.github/workflows/npm-release.yml b/.github/workflows/npm-release.yml index 1e34b17..4a95990 100644 --- a/.github/workflows/npm-release.yml +++ b/.github/workflows/npm-release.yml @@ -6,7 +6,7 @@ on: version: description: Lockstep version for all release packages required: true - default: 0.3.3 + default: 0.3.4 type: string publish_to_registry: description: Publish the fully gated candidate to npm after preflight diff --git a/CHANGELOG.md b/CHANGELOG.md index d244648..eefc252 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ This file records user-visible changes to `light-ocr`. Published artifact details and immutable hashes remain in [`docs/releases/`](docs/releases/). +## [0.3.4] - 2026-07-22 + +### Fixed + +- Fixed the native Node-API option contract so the documented `region` option reaches the existing ROI implementation for both `recognize` and `detect`, including valid zero-based `x` and `y` coordinates. +- Extended the existing package smoke to execute a real `light-ocr recognize --region` command, covering CLI argument parsing, encoded-image decoding, native option admission, model inference, and text output in one focused check. + ## [0.3.3] - 2026-07-22 ### Fixed diff --git a/CMakeLists.txt b/CMakeLists.txt index 3b2c552..daa9dab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,7 @@ if(APPLE AND (NOT DEFINED CMAKE_OSX_DEPLOYMENT_TARGET OR "Minimum macOS deployment target" FORCE) endif() -project(light_ocr VERSION 0.3.3 LANGUAGES CXX) +project(light_ocr VERSION 0.3.4 LANGUAGES CXX) if(APPLE) enable_language(OBJCXX) diff --git a/bindings/node/bin/light-ocr.cjs b/bindings/node/bin/light-ocr.cjs index 361e285..de3b251 100755 --- a/bindings/node/bin/light-ocr.cjs +++ b/bindings/node/bin/light-ocr.cjs @@ -19,7 +19,7 @@ const { createEngine, OcrError } = require('../js/index.cjs'); const { parseExifOrientation } = require('../js/exif.cjs'); const PKG_VERSION = require('../package.json').version; -const CORE_VERSION = '0.3.3'; +const CORE_VERSION = '0.3.4'; const SUBCOMMANDS = new Set(['recognize', 'detect', 'info']); const EXIT = { diff --git a/bindings/node/package.json b/bindings/node/package.json index 4792233..dca8d95 100644 --- a/bindings/node/package.json +++ b/bindings/node/package.json @@ -1,6 +1,6 @@ { "name": "@arcships/light-ocr", - "version": "0.3.3", + "version": "0.3.4", "private": true, "description": "Node-API adapter for the light-ocr C++ core", "license": "Apache-2.0", diff --git a/bindings/node/src/addon.cpp b/bindings/node/src/addon.cpp index 4748c5b..0005ff9 100644 --- a/bindings/node/src/addon.cpp +++ b/bindings/node/src/addon.cpp @@ -760,7 +760,7 @@ RecognizeOptions parse_recognize_options(napi_env env, napi_value value, require_object(env, value, "recognize options"); const std::unordered_set allowed{ "recognitionScoreThreshold", "recognitionBatchSize", "includeDiagnostics", - "useTextlineOrientation", "detectionMaxSide", "applyExif"}; + "useTextlineOrientation", "detectionMaxSide", "applyExif", "region"}; reject_unknown_properties(env, value, allowed, "recognize options"); if (const auto option = optional_named(env, value, "recognitionScoreThreshold")) { const double score = get_number(env, *option, "recognitionScoreThreshold"); @@ -804,8 +804,8 @@ RecognizeOptions parse_recognize_options(napi_env env, napi_value value, const std::unordered_set region_allowed{"x", "y", "width", "height"}; reject_unknown_properties(env, *option, region_allowed, "region"); Rect rect; - rect.x = get_u32(env, *optional_named(env, *option, "x"), "region.x", 1); - rect.y = get_u32(env, *optional_named(env, *option, "y"), "region.y", 1); + rect.x = get_u32(env, *optional_named(env, *option, "x"), "region.x", 0); + rect.y = get_u32(env, *optional_named(env, *option, "y"), "region.y", 0); rect.width = get_u32(env, *optional_named(env, *option, "width"), "region.width", 1); rect.height = get_u32(env, *optional_named(env, *option, "height"), "region.height", 1); if (rect.width == 0 || rect.height == 0) { diff --git a/tools/npm/smoke.cjs b/tools/npm/smoke.cjs index 284469b..639bac8 100644 --- a/tools/npm/smoke.cjs +++ b/tools/npm/smoke.cjs @@ -5,6 +5,11 @@ const { spawnSync } = require('node:child_process'); const fs = require('node:fs'); const path = require('node:path'); +const encodedBlankPng = Buffer.from( + 'iVBORw0KGgoAAAANSUhEUgAAAAIAAAADCAIAAAA2iEnWAAAAFUlEQVR4nGP8//8/AwMDEwMDA4ICADkbAwP+wj6MAAAAAElFTkSuQmCC', + 'base64', +); + async function main() { const fixtureDirectory = process.env.LIGHT_OCR_SMOKE_FIXTURE; assert.ok(fixtureDirectory, 'LIGHT_OCR_SMOKE_FIXTURE is required'); @@ -35,6 +40,24 @@ async function main() { assert.equal(versionTriple.npm, packageMetadata.version); assert.equal(versionTriple.core, packageMetadata.version); assert.equal(versionTriple.model, 'ppocrv6-small-native-20260719.1'); + const cliRecognition = spawnSync( + cli, + [ + 'recognize', '--stdin', '--type', 'image/png', '--format', 'text', + '--region', '0,0,2,3', + ], + { + input: encodedBlankPng, + encoding: 'utf8', + shell: process.platform === 'win32', + }, + ); + assert.equal( + cliRecognition.status, + 0, + cliRecognition.stderr || cliRecognition.error?.message, + ); + assert.equal(cliRecognition.stdout, ''); const appleSupported = process.platform === 'darwin' && process.arch === 'arm64'; assert.strictEqual(esm.createEngine, cjs.createEngine); assert.strictEqual(esm.OcrError, cjs.OcrError);