From 6ad996d1d466409ee96cd15e5e2dccff25bd712a Mon Sep 17 00:00:00 2001 From: figulusproject <269854178+figulusproject@users.noreply.github.com> Date: Mon, 3 Aug 2026 10:20:01 -0400 Subject: [PATCH 1/6] fix wasm/browser-entry.js failing to import on Node 20: - rename to wasm/browser-entry.mjs -- Node 20 lacks the fallback that reparses typeless .js files as ESM, so import() hit them through the CJS loader and errored on the `import` statement. .mjs avoids the ambiguity - update the filename in package.json ("browser"/"files"), index.d.ts, lib/detect-shape.js, lib/wasm-wrap.js, and test/runner-wasm-browser.js --- index.d.ts | 2 +- lib/detect-shape.js | 2 +- lib/wasm-wrap.js | 2 +- package.json | 4 ++-- test/runner-wasm-browser.js | 10 +++++----- wasm/{browser-entry.js => browser-entry.mjs} | 0 6 files changed, 10 insertions(+), 10 deletions(-) rename wasm/{browser-entry.js => browser-entry.mjs} (100%) diff --git a/index.d.ts b/index.d.ts index 6ba6160..172a064 100644 --- a/index.d.ts +++ b/index.d.ts @@ -29,7 +29,7 @@ export const LANGUAGES: {[name: string]: string}; export const DETECTED_LANGUAGES: string[]; export const ENCODINGS: string[]; -// Browser entry point only (./wasm/browser-entry.js). Overrides where the +// Browser entry point only (./wasm/browser-entry.mjs). Overrides where the // WASM backend fetches cld.web.wasm from -- has no effect on the native // backend. Must be called before the first detect() call. export declare function setWasmModuleOptions(options: { locateFile?: (path: string, scriptDirectory: string) => string }): void; diff --git a/lib/detect-shape.js b/lib/detect-shape.js index c997efe..5f5567e 100644 --- a/lib/detect-shape.js +++ b/lib/detect-shape.js @@ -1,5 +1,5 @@ // Shared detect() implementation used by both index.js (Node, native-first -// with WASM fallback) and wasm/browser-entry.js (bundler/browser, WASM +// with WASM fallback) and wasm/browser-entry.mjs (bundler/browser, WASM // only) -- the validation/defaults/error-mapping logic is identical for // both, only how the backend is loaded differs. diff --git a/lib/wasm-wrap.js b/lib/wasm-wrap.js index e699382..28b00ac 100644 --- a/lib/wasm-wrap.js +++ b/lib/wasm-wrap.js @@ -1,7 +1,7 @@ // Wraps an instantiated Emscripten module (Node or browser target -- both // expose the same ccall/UTF8ToString shape) into the {detectAsync(...)} // interface shared with the native backend. Deliberately has no other -// requires: wasm/browser-entry.js imports this directly (not through +// requires: wasm/browser-entry.mjs imports this directly (not through // lib/backend.js) so bundlers never see lib/backend.js's // require('../build/Release/cld') at all. diff --git a/package.json b/package.json index 41f0a58..46c3977 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "exports": { ".": { "types": "./index.d.ts", - "browser": "./wasm/browser-entry.js", + "browser": "./wasm/browser-entry.mjs", "default": "./index.js" } }, @@ -25,7 +25,7 @@ "index.d.ts", "lib", "wasm/dist", - "wasm/browser-entry.js", + "wasm/browser-entry.mjs", "src", "deps/cld/public", "deps/cld/internal", diff --git a/test/runner-wasm-browser.js b/test/runner-wasm-browser.js index 168a932..5c01fc2 100644 --- a/test/runner-wasm-browser.js +++ b/test/runner-wasm-browser.js @@ -1,14 +1,14 @@ #!/usr/bin/env node -// Proves wasm/browser-entry.js's setWasmModuleOptions({ locateFile }) hook +// Proves wasm/browser-entry.mjs's setWasmModuleOptions({ locateFile }) hook // actually controls where the WASM backend fetches cld.web.wasm from -- // not just that the option is accepted, but that redirecting it to a // custom URL is what makes detection succeed. // -// Each case runs in its own child process: browser-entry.js caches +// Each case runs in its own child process: browser-entry.mjs caches // moduleOptions/modulePromise at module scope on first use, so "no // override" and "with override" can't share one process/import. // -// With no override, browser-entry.js's default WASM URL resolves against +// With no override, browser-entry.mjs's default WASM URL resolves against // import.meta.url, which is a file:// URL here -- and Node's fetch() // doesn't support file://, so detect() is expected to reject. That's not a // Node quirk being worked around, it's exactly the gap the override exists @@ -39,7 +39,7 @@ function runChild(script) { (async () => { const withoutOverride = ` - import('../wasm/browser-entry.js') + import('../wasm/browser-entry.mjs') .then(m => m.detect(${JSON.stringify(SAMPLE.sample)})) .then(() => { console.log('UNEXPECTED_SUCCESS'); process.exit(0); }) .catch(() => { console.log('EXPECTED_FAILURE'); process.exit(0); }); @@ -58,7 +58,7 @@ function runChild(script) { try { const withOverride = ` - import('../wasm/browser-entry.js').then(async m => { + import('../wasm/browser-entry.mjs').then(async m => { m.setWasmModuleOptions({ locateFile: () => 'http://127.0.0.1:${port}/custom-path/cld.web.wasm' }); const result = await m.detect(${JSON.stringify(SAMPLE.sample)}); console.log(JSON.stringify(result.languages[0])); diff --git a/wasm/browser-entry.js b/wasm/browser-entry.mjs similarity index 100% rename from wasm/browser-entry.js rename to wasm/browser-entry.mjs From c6b9f8ef8a3504f9aab352cb2092457b6b067c7d Mon Sep 17 00:00:00 2001 From: figulusproject <269854178+figulusproject@users.noreply.github.com> Date: Mon, 3 Aug 2026 10:26:05 -0400 Subject: [PATCH 2/6] add changelog entry for browser entry extension fix --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a037e66..2a5683f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,12 @@ This fork ([`cld-universal`](https://github.com/figulusproject/cld-universal)) d [`dachev/node-cld`](https://github.com/dachev/node-cld) at `2.10.1`. Entries below start from that point. +## [Upcoming] + +### Fixed + +- Browser entry point renamed from `wasm/browser-entry.js` to `wasm/browser-entry.mjs`. Node 20 lacks the fallback that reparses typeless .js files as ESM, so import() hit them through the CJS loader and errored on the `import` statement. Renaming it to use an MJS extension avoids the ambiguity. + ## [2.11.1] - 2026-08-03 ### Added From efba5a7c834ef1895adf02f14057c1041e4f2d50 Mon Sep 17 00:00:00 2001 From: figulusproject <269854178+figulusproject@users.noreply.github.com> Date: Mon, 3 Aug 2026 10:36:58 -0400 Subject: [PATCH 3/6] attach WASM artifacts to the tag's GitHub release: - grant contents: write so the workflow can create/update releases - add step extracting the matching version's section from CHANGELOG.md into release notes -- fails the run if no entry exists for the tag - add step creating a GitHub release for the pushed tag (or uploading with --clobber if one already exists) with wasm/dist's four build outputs attached as assets --- .github/workflows/publish.yml | 39 ++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 79834d3..9e522a8 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -7,6 +7,7 @@ on: permissions: id-token: write + contents: write jobs: publish: @@ -35,4 +36,40 @@ jobs: run: npm run build && npm run build:wasm - name: Publish - run: npm publish --access public \ No newline at end of file + run: npm publish --access public + + - name: Extract changelog entry + run: | + VERSION="${GITHUB_REF_NAME#v}" + awk -v ver="$VERSION" ' + /^## \[/ { + if (capture) exit + if ($0 ~ "^## \\[" ver "\\]") { capture=1; next } + next + } + capture { print } + ' CHANGELOG.md > /tmp/release-notes.md + + if [ ! -s /tmp/release-notes.md ]; then + echo "error: no CHANGELOG.md entry found for version ${VERSION}" >&2 + exit 1 + fi + + - name: Attach WASM artifacts to GitHub release + env: + GH_TOKEN: ${{ github.token }} + run: | + ASSETS=( + wasm/dist/cld.node.js + wasm/dist/cld.node.wasm + wasm/dist/cld.web.mjs + wasm/dist/cld.web.wasm + ) + if gh release view "${GITHUB_REF_NAME}" >/dev/null 2>&1; then + gh release upload "${GITHUB_REF_NAME}" "${ASSETS[@]}" --clobber + else + gh release create "${GITHUB_REF_NAME}" \ + --title "${GITHUB_REF_NAME}" \ + --notes-file /tmp/release-notes.md \ + "${ASSETS[@]}" + fi \ No newline at end of file From 3074f9e0576bf356c6f60bc43ff2931557764e51 Mon Sep 17 00:00:00 2001 From: figulusproject <269854178+figulusproject@users.noreply.github.com> Date: Mon, 3 Aug 2026 10:38:18 -0400 Subject: [PATCH 4/6] add changelog entry for release workflow addition --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a5683f..c47af0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,10 @@ point. ## [Upcoming] +### Changed + +- Publish workflow (`publish.yml`) now attaches the built WASM artifacts (`cld.node.js`, `cld.node.wasm`, `cld.web.mjs`, `cld.web.wasm`) to the pushed tag's GitHub release, using the matching version's entry from this changelog as the release notes. + ### Fixed - Browser entry point renamed from `wasm/browser-entry.js` to `wasm/browser-entry.mjs`. Node 20 lacks the fallback that reparses typeless .js files as ESM, so import() hit them through the CJS loader and errored on the `import` statement. Renaming it to use an MJS extension avoids the ambiguity. From 6de9ed386ff186a860ee9af7de14b39f293e6c3a Mon Sep 17 00:00:00 2001 From: figulusproject <269854178+figulusproject@users.noreply.github.com> Date: Mon, 3 Aug 2026 11:23:37 -0400 Subject: [PATCH 5/6] move readme banners to profile readme --- README.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/README.md b/README.md index 0eb6e73..551c733 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,7 @@ [![CI](https://github.com/figulusproject/cld-universal/actions/workflows/ci.yml/badge.svg)](https://github.com/figulusproject/cld-universal/actions/workflows/ci.yml) [![NPM version](https://badge.fury.io/js/cld-universal.svg)](http://badge.fury.io/js/cld-universal) -[![Stand With Palestine](https://raw.githubusercontent.com/standforhumanity/stand-with-palestine/main/Banners/Banner1.svg)](https://stand-with-palestine.vercel.app/) - -[![Stand With Ukraine](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/banner2-direct.svg)](https://stand-with-ukraine.pp.ua) - -*Fork developed on stolen Wurundjeri Land. We pay our respects to Elders past, present, and emerging, and with all peoples resisting occupation.* +*Everyone has the right to resist occupation.* > **This is a fork of [dachev/node-cld](https://github.com/dachev/node-cld).** The original project has had no maintainer activity in over a year, and has outdated dependencies causing 3 high severity security issues. > From 98ffe1edba35bcae1c7ecbc7f6f6c9b23bfa890a Mon Sep 17 00:00:00 2001 From: figulusproject <269854178+figulusproject@users.noreply.github.com> Date: Mon, 3 Aug 2026 11:23:46 -0400 Subject: [PATCH 6/6] version++ --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c47af0a..00721ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ This fork ([`cld-universal`](https://github.com/figulusproject/cld-universal)) d [`dachev/node-cld`](https://github.com/dachev/node-cld) at `2.10.1`. Entries below start from that point. -## [Upcoming] +## [2.11.2] - 2026-08-03 ### Changed diff --git a/package-lock.json b/package-lock.json index 05ddf14..d24858a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "cld-universal", - "version": "2.11.1", + "version": "2.11.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "cld-universal", - "version": "2.11.1", + "version": "2.11.2", "hasInstallScript": true, "dependencies": { "glob": "^12", diff --git a/package.json b/package.json index 46c3977..4383ca9 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "wasm", "webassembly" ], - "version": "2.11.1", + "version": "2.11.2", "main": "./index.js", "types": "./index.d.ts", "exports": {