Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 38 additions & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ on:

permissions:
id-token: write
contents: write

jobs:
publish:
Expand Down Expand Up @@ -35,4 +36,40 @@ jobs:
run: npm run build && npm run build:wasm

- name: Publish
run: npm publish --access public
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
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@ 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.

## [2.11.2] - 2026-08-03

### 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.

## [2.11.1] - 2026-08-03

### Added
Expand Down
6 changes: 1 addition & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
>
Expand Down
2 changes: 1 addition & 1 deletion index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion lib/detect-shape.js
Original file line number Diff line number Diff line change
@@ -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.

Expand Down
2 changes: 1 addition & 1 deletion lib/wasm-wrap.js
Original file line number Diff line number Diff line change
@@ -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.

Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@
"wasm",
"webassembly"
],
"version": "2.11.1",
"version": "2.11.2",
"main": "./index.js",
"types": "./index.d.ts",
"exports": {
".": {
"types": "./index.d.ts",
"browser": "./wasm/browser-entry.js",
"browser": "./wasm/browser-entry.mjs",
"default": "./index.js"
}
},
Expand All @@ -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",
Expand Down
10 changes: 5 additions & 5 deletions test/runner-wasm-browser.js
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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); });
Expand All @@ -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]));
Expand Down
File renamed without changes.
Loading