lingotweaker-wasm 0.0.1 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +80 -4
- package/pack.js +76 -0
- package/package.json +49 -3
package/README.md
CHANGED
|
@@ -1,5 +1,81 @@
|
|
|
1
|
-
#
|
|
1
|
+
# LingoTweaker (WebAssembly)
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
WebAssembly bindings for the LingoTweaker proofreading engine (wasm-bindgen),
|
|
4
|
+
for browsers and Node.js. The engine runs entirely from an in-memory data pack,
|
|
5
|
+
so no file system or native addon is required.
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
npm install lingotweaker-wasm@next
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Browser
|
|
12
|
+
|
|
13
|
+
```js
|
|
14
|
+
import init, { LtEngine } from "lingotweaker-wasm";
|
|
15
|
+
import { fetchPack } from "lingotweaker-wasm/pack";
|
|
16
|
+
|
|
17
|
+
await init();
|
|
18
|
+
|
|
19
|
+
const pack = await fetchPack("en"); // release asset for this package version
|
|
20
|
+
const engine = new LtEngine(
|
|
21
|
+
"en-US",
|
|
22
|
+
pack,
|
|
23
|
+
JSON.stringify({ today: new Date().toISOString() }),
|
|
24
|
+
);
|
|
25
|
+
const result = JSON.parse(engine.check_json("I can heard you."));
|
|
26
|
+
for (const match of result.matches) {
|
|
27
|
+
console.log(match.rule_id, match.suggestions);
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Node.js
|
|
32
|
+
|
|
33
|
+
The Node build is CommonJS (`lingotweaker-wasm/node`); the data helper is ESM,
|
|
34
|
+
so import it dynamically from CJS:
|
|
35
|
+
|
|
36
|
+
```js
|
|
37
|
+
const { LtEngine } = require("lingotweaker-wasm/node");
|
|
38
|
+
|
|
39
|
+
(async () => {
|
|
40
|
+
const { fetchPack } = await import("lingotweaker-wasm/pack");
|
|
41
|
+
const pack = await fetchPack("en");
|
|
42
|
+
const engine = new LtEngine(
|
|
43
|
+
"en-US",
|
|
44
|
+
pack,
|
|
45
|
+
JSON.stringify({ today: new Date().toISOString() }),
|
|
46
|
+
);
|
|
47
|
+
console.log(engine.check_json("I can heard you."));
|
|
48
|
+
})();
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Or, from an ES module: `import { LtEngine } from "lingotweaker-wasm/node"`.
|
|
52
|
+
|
|
53
|
+
`today` is required in practice: WebAssembly has no clock, so the date is
|
|
54
|
+
passed in and pinned for the engine's date filters.
|
|
55
|
+
|
|
56
|
+
## Data
|
|
57
|
+
|
|
58
|
+
The package ships **code only** and depends on `lingotweaker-data`, which
|
|
59
|
+
carries one gzipped pack per language. In Node.js the data helper resolves that
|
|
60
|
+
package locally; in the browser (or without it) it falls back to the per-release
|
|
61
|
+
GitHub Release assets:
|
|
62
|
+
|
|
63
|
+
```js
|
|
64
|
+
import { fetchPack, packUrl, manifestUrl } from "lingotweaker-wasm/pack";
|
|
65
|
+
|
|
66
|
+
await fetchPack("en"); // local lingotweaker-data in Node, else release assets
|
|
67
|
+
await fetchPack("gn", { baseUrl: "https://fiduswriter.github.io/LingoTweaker" });
|
|
68
|
+
packUrl("de"); // build a URL yourself
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
`baseUrl` points at a directory that contains `packs/<lang>.pack.gz` and
|
|
72
|
+
`manifest.json`. All languages are attached to every release; `manifest.json`
|
|
73
|
+
lists file sizes and sha256 hashes. `lingotweaker-data` is also served from any
|
|
74
|
+
npm CDN (`https://cdn.jsdelivr.net/npm/lingotweaker-data/packs/<lang>.pack.gz`),
|
|
75
|
+
and you can host the packs yourself.
|
|
76
|
+
|
|
77
|
+
LingoTweaker is an independent project and includes a port of the legacy
|
|
78
|
+
LanguageTool proofreading engine and its rule data. Upstream references and
|
|
79
|
+
licenses are kept; see `THIRD_PARTY_NOTICES.md` in the repository.
|
|
80
|
+
|
|
81
|
+
License: LGPL-2.1-or-later.
|
package/pack.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// Data helpers for the `lingotweaker-wasm` package.
|
|
2
|
+
//
|
|
3
|
+
// The engine itself is loaded from an in-memory data pack
|
|
4
|
+
// (`LtEngine(lang, pack, optionsJson)`); this module fetches those packs from
|
|
5
|
+
// the per-release GitHub Release assets and inflates the gzip wrapper.
|
|
6
|
+
//
|
|
7
|
+
// import { fetchPack } from "lingotweaker-wasm/pack";
|
|
8
|
+
// const pack = await fetchPack("en");
|
|
9
|
+
// const engine = new LtEngine("en-US", pack, JSON.stringify({ today: new Date().toISOString() }));
|
|
10
|
+
|
|
11
|
+
// Updated by scripts/release/set-version.sh together with the package version.
|
|
12
|
+
export const DEFAULT_DATA_BASE_URL =
|
|
13
|
+
"https://github.com/fiduswriter/LingoTweaker/releases/download/v0.1.1";
|
|
14
|
+
|
|
15
|
+
/** The URL of the release data manifest (`{ <lang>: { file, bytes, sha256 } }`). */
|
|
16
|
+
export function manifestUrl(baseUrl = DEFAULT_DATA_BASE_URL) {
|
|
17
|
+
return `${baseUrl}/manifest.json`;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** The URL of the gzipped pack for `lang`. */
|
|
21
|
+
export function packUrl(lang, baseUrl = DEFAULT_DATA_BASE_URL) {
|
|
22
|
+
return `${baseUrl}/packs/${lang}.pack.gz`;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Inflate a gzipped pack (browser `DecompressionStream`, else Node `zlib`). */
|
|
26
|
+
export async function decompressPack(bytes) {
|
|
27
|
+
const u8 = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes);
|
|
28
|
+
if (typeof DecompressionStream === "function" && typeof Blob === "function") {
|
|
29
|
+
const stream = new Blob([u8]).stream().pipeThrough(new DecompressionStream("gzip"));
|
|
30
|
+
return new Uint8Array(await new Response(stream).arrayBuffer());
|
|
31
|
+
}
|
|
32
|
+
const { gunzipSync } = await import("node:zlib");
|
|
33
|
+
return new Uint8Array(gunzipSync(u8));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Fetch and inflate the pack for `lang` (`en`, `de`, `gn`, …).
|
|
38
|
+
*
|
|
39
|
+
* Node.js prefers the locally installed `lingotweaker-data` package; browsers
|
|
40
|
+
* (and any environment without it) fall back to the release assets for this
|
|
41
|
+
* package version. Pass `baseUrl` to use different data — the Pages demo
|
|
42
|
+
* (`https://fiduswriter.github.io/LingoTweaker`) or a local directory.
|
|
43
|
+
*/
|
|
44
|
+
export async function fetchPack(lang, options = {}) {
|
|
45
|
+
const { fetch: fetchImpl = fetch } = options;
|
|
46
|
+
let { baseUrl } = options;
|
|
47
|
+
if (!baseUrl) {
|
|
48
|
+
const local = await localPack(lang);
|
|
49
|
+
if (local) return local;
|
|
50
|
+
baseUrl = DEFAULT_DATA_BASE_URL;
|
|
51
|
+
}
|
|
52
|
+
const url = packUrl(lang, baseUrl);
|
|
53
|
+
const response = await fetchImpl(url);
|
|
54
|
+
if (!response.ok) {
|
|
55
|
+
throw new Error(`cannot load ${url}: HTTP ${response.status}`);
|
|
56
|
+
}
|
|
57
|
+
return decompressPack(await response.arrayBuffer());
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Read and inflate a pack from the installed `lingotweaker-data` package.
|
|
62
|
+
* Returns `null` outside Node.js, or when the package/language is missing.
|
|
63
|
+
*/
|
|
64
|
+
export async function localPack(lang) {
|
|
65
|
+
if (typeof process === "undefined" || !process.versions?.node) return null;
|
|
66
|
+
try {
|
|
67
|
+
const { createRequire } = await import("node:module");
|
|
68
|
+
const require = createRequire(import.meta.url);
|
|
69
|
+
const data = require("lingotweaker-data");
|
|
70
|
+
const { readFile } = await import("node:fs/promises");
|
|
71
|
+
const bytes = await readFile(data.packPath(lang));
|
|
72
|
+
return decompressPack(bytes);
|
|
73
|
+
} catch {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
}
|
package/package.json
CHANGED
|
@@ -1,11 +1,57 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lingotweaker-wasm",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "LingoTweaker proofreading engine compiled to WebAssembly",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "LingoTweaker proofreading engine compiled to WebAssembly (browser and Node)",
|
|
5
5
|
"license": "LGPL-2.1-or-later",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "git+https://github.com/fiduswriter/LingoTweaker.git"
|
|
9
9
|
},
|
|
10
|
-
"homepage": "https://fiduswriter.github.io/LingoTweaker/"
|
|
10
|
+
"homepage": "https://fiduswriter.github.io/LingoTweaker/",
|
|
11
|
+
"keywords": [
|
|
12
|
+
"proofreading",
|
|
13
|
+
"grammar",
|
|
14
|
+
"spellcheck",
|
|
15
|
+
"nlp",
|
|
16
|
+
"language",
|
|
17
|
+
"wasm",
|
|
18
|
+
"webassembly"
|
|
19
|
+
],
|
|
20
|
+
"type": "module",
|
|
21
|
+
"main": "./node/lt_wasm.js",
|
|
22
|
+
"module": "./web/lt_wasm.js",
|
|
23
|
+
"types": "./web/lt_wasm.d.ts",
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"lingotweaker-data": "0.1.1"
|
|
26
|
+
},
|
|
27
|
+
"exports": {
|
|
28
|
+
".": {
|
|
29
|
+
"types": "./web/lt_wasm.d.ts",
|
|
30
|
+
"browser": "./web/lt_wasm.js",
|
|
31
|
+
"import": "./web/lt_wasm.js",
|
|
32
|
+
"require": "./node/lt_wasm.js",
|
|
33
|
+
"default": "./web/lt_wasm.js"
|
|
34
|
+
},
|
|
35
|
+
"./web": {
|
|
36
|
+
"types": "./web/lt_wasm.d.ts",
|
|
37
|
+
"default": "./web/lt_wasm.js"
|
|
38
|
+
},
|
|
39
|
+
"./node": {
|
|
40
|
+
"types": "./node/lt_wasm.d.ts",
|
|
41
|
+
"default": "./node/lt_wasm.js"
|
|
42
|
+
},
|
|
43
|
+
"./pack": {
|
|
44
|
+
"default": "./pack.js"
|
|
45
|
+
},
|
|
46
|
+
"./package.json": "./package.json"
|
|
47
|
+
},
|
|
48
|
+
"files": [
|
|
49
|
+
"web",
|
|
50
|
+
"node",
|
|
51
|
+
"pack.js",
|
|
52
|
+
"README.md"
|
|
53
|
+
],
|
|
54
|
+
"engines": {
|
|
55
|
+
"node": ">= 18"
|
|
56
|
+
}
|
|
11
57
|
}
|