@gmb/bitmark-parser 6.0.1 → 6.1.0
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/dist/browser/bitmark-parser.min.js +2 -1
- package/dist/browser/bitmark-parser.min.js.map +1 -1
- package/dist/browser/bitmark_wasm_bg.wasm +0 -0
- package/dist/browser/cjs/bitmark_wasm_bg.wasm +0 -0
- package/dist/browser/cjs/index.cjs +458 -26
- package/dist/browser/cjs/index.cjs.map +1 -1
- package/dist/browser/cjs/index.d.cts +155 -2
- package/dist/browser/esm/bitmark_wasm_bg.wasm +0 -0
- package/dist/browser/esm/index.d.ts +155 -2
- package/dist/browser/esm/index.js +456 -26
- package/dist/browser/esm/index.js.map +1 -1
- package/dist/browser/esm/worker-entry.d.ts +2 -0
- package/dist/browser/esm/worker-entry.js +191 -0
- package/dist/browser/esm/worker-entry.js.map +1 -0
- package/dist/cli.js +219 -7
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +265 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +167 -4
- package/dist/index.d.ts +167 -4
- package/dist/index.js +257 -4
- package/dist/index.js.map +1 -1
- package/dist/worker-entry.cjs +39 -0
- package/dist/worker-entry.cjs.map +1 -0
- package/package.json +3 -2
- package/wasm/bitmark_wasm.d.ts +70 -22
- package/wasm/bitmark_wasm.js +302 -55
- package/wasm/bitmark_wasm_bg.wasm +0 -0
- package/wasm/bitmark_wasm_bg.wasm.d.ts +10 -1
- package/wasm/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -22,8 +22,16 @@ interface ParseOptions {
|
|
|
22
22
|
/** JSON output mode (default: `"optimized"`). */
|
|
23
23
|
mode?: OutputMode;
|
|
24
24
|
}
|
|
25
|
+
/** Input format selector (adds auto-detection). */
|
|
26
|
+
type InputFormat = "auto" | "bitmark" | "json";
|
|
27
|
+
/** Concrete output format. */
|
|
28
|
+
type OutputFormat = "bitmark" | "json";
|
|
25
29
|
/** Options for the {@link convert} function. */
|
|
26
30
|
interface ConvertOptions {
|
|
31
|
+
/** Input format (default: `"auto"`). */
|
|
32
|
+
inputFormat?: InputFormat;
|
|
33
|
+
/** Output format (default: `"auto"` — the opposite of the input). */
|
|
34
|
+
outputFormat?: OutputFormat | "auto";
|
|
27
35
|
/** JSON output mode (default: `"optimized"`). */
|
|
28
36
|
mode?: OutputMode;
|
|
29
37
|
/** Include validation warnings in `parser.warnings` output (default: `false`). */
|
|
@@ -34,6 +42,104 @@ interface ConvertOptions {
|
|
|
34
42
|
pretty?: boolean;
|
|
35
43
|
/** Indent size for pretty-printing (default: `2`). */
|
|
36
44
|
indent?: number;
|
|
45
|
+
/** Spaces around tag values in bitmark output, `0..=10` (default: `1`). */
|
|
46
|
+
spacesAroundValues?: number;
|
|
47
|
+
}
|
|
48
|
+
/** Options for the {@link optimize}, {@link fullize}, and {@link canonicalize} functions. */
|
|
49
|
+
interface NormalizeOptions {
|
|
50
|
+
/** Output mode — used by {@link canonicalize} only (default: `"optimized"`). */
|
|
51
|
+
mode?: OutputMode;
|
|
52
|
+
/** Prettify JSON output (default: `false`). */
|
|
53
|
+
pretty?: boolean;
|
|
54
|
+
/** Indent size for pretty-printing (default: `2`). */
|
|
55
|
+
indent?: number;
|
|
56
|
+
/** Spaces around tag values in bitmark output, `0..=10` (default: `1`). */
|
|
57
|
+
spacesAroundValues?: number;
|
|
58
|
+
}
|
|
59
|
+
/** A patch operation. */
|
|
60
|
+
type PatchOp = "set" | "create" | "delete" | "append";
|
|
61
|
+
/**
|
|
62
|
+
* A patch entry. Either the verbose form `{ path, op, value? }` or the
|
|
63
|
+
* shorthand single-key object `{ "<path>": value }` (which means `set`).
|
|
64
|
+
*
|
|
65
|
+
* `path` addresses the bit JSON directly (e.g. `id`,
|
|
66
|
+
* `cards[2].question.instruction`, `id[-1]`). To modify bitmark, convert to
|
|
67
|
+
* JSON, patch, then convert back — `transform` does this when the output
|
|
68
|
+
* format is bitmark.
|
|
69
|
+
*/
|
|
70
|
+
type PatchEntry = {
|
|
71
|
+
path: string;
|
|
72
|
+
op: PatchOp;
|
|
73
|
+
value?: unknown;
|
|
74
|
+
} | Record<string, unknown>;
|
|
75
|
+
/** One bit's source slice within a bitmark document (from {@link splitBits}). */
|
|
76
|
+
interface BitSlice {
|
|
77
|
+
index: number;
|
|
78
|
+
byteStart: number;
|
|
79
|
+
byteEnd: number;
|
|
80
|
+
source: string;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* What a {@link PreHook} / {@link PostHook} sees for one bit, in its source
|
|
84
|
+
* format. `index` is the bit's 0-based position; `total` is the bit count.
|
|
85
|
+
*/
|
|
86
|
+
type BitView = {
|
|
87
|
+
format: "bitmark";
|
|
88
|
+
index: number;
|
|
89
|
+
total: number;
|
|
90
|
+
source: string;
|
|
91
|
+
} | {
|
|
92
|
+
format: "json";
|
|
93
|
+
index: number;
|
|
94
|
+
total: number;
|
|
95
|
+
bit: unknown;
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* What a {@link PreHook} may return for a bit. All fields are optional; an
|
|
99
|
+
* empty result (or `void`) makes the hook a pure observer.
|
|
100
|
+
*/
|
|
101
|
+
interface PreHookResult {
|
|
102
|
+
/** Patches to apply to this bit, after any static `patch`. */
|
|
103
|
+
patches?: PatchEntry[];
|
|
104
|
+
/** Override the output format for this bit only. */
|
|
105
|
+
outputFormat?: OutputFormat;
|
|
106
|
+
/** Drop the bit from the output entirely. */
|
|
107
|
+
drop?: boolean;
|
|
108
|
+
}
|
|
109
|
+
/** Pre-processing hook: inspect a bit, optionally return modifications. */
|
|
110
|
+
type PreHook = (view: BitView) => PreHookResult | void;
|
|
111
|
+
/** Post-processing hook: observe a bit's input view and rendered output. */
|
|
112
|
+
type PostHook = (view: BitView, output: string) => void;
|
|
113
|
+
/** Options for the {@link transform} function. */
|
|
114
|
+
interface TransformOptions {
|
|
115
|
+
/** Input format (default: `"auto"`). */
|
|
116
|
+
inputFormat?: InputFormat;
|
|
117
|
+
/** Output format (default: `"json"`). */
|
|
118
|
+
outputFormat?: OutputFormat;
|
|
119
|
+
/** Output mode (default: `"optimized"`). */
|
|
120
|
+
mode?: OutputMode;
|
|
121
|
+
/** A static patch applied to every bit (array of entries, or a JSON string). */
|
|
122
|
+
patch?: PatchEntry[] | string;
|
|
123
|
+
/**
|
|
124
|
+
* Per-bit pre-hook, run on the calling thread. Returns patches (applied
|
|
125
|
+
* after the static `patch`), an output-format override, or `drop`. Providing
|
|
126
|
+
* a `preHook` or `postHook` switches `transform` to the per-bit path; with
|
|
127
|
+
* neither, the whole document is transformed in a single pass.
|
|
128
|
+
*/
|
|
129
|
+
preHook?: PreHook;
|
|
130
|
+
/** Per-bit post-hook, run on the calling thread after each bit is rendered. */
|
|
131
|
+
postHook?: PostHook;
|
|
132
|
+
/**
|
|
133
|
+
* Worker-thread count for {@link transformParallel} (Node only; default `4`).
|
|
134
|
+
* Ignored by the synchronous {@link transform}.
|
|
135
|
+
*/
|
|
136
|
+
workers?: number;
|
|
137
|
+
/** Prettify JSON output (default: `false`). */
|
|
138
|
+
pretty?: boolean;
|
|
139
|
+
/** Indent size for pretty-printing (default: `2`). */
|
|
140
|
+
indent?: number;
|
|
141
|
+
/** Spaces around tag values in bitmark output, `0..=10` (default: `1`). */
|
|
142
|
+
spacesAroundValues?: number;
|
|
37
143
|
}
|
|
38
144
|
/** Text format for breakscape / unbreakscape operations. */
|
|
39
145
|
type TextFormat = "bitmark++" | "plainText";
|
|
@@ -97,6 +203,60 @@ declare function parse(input: string, options?: ParseOptions): string;
|
|
|
97
203
|
* array of structured parsed entries (`bit`, `parser`, `bitmark`).
|
|
98
204
|
*/
|
|
99
205
|
declare function convert(input: string, options?: ConvertOptions): string;
|
|
206
|
+
/**
|
|
207
|
+
* Re-emit input in its own (auto-detected) format at optimized mode.
|
|
208
|
+
*
|
|
209
|
+
* @param input - Bitmark or JSON input text.
|
|
210
|
+
* @returns Optimized output in the same format as the input.
|
|
211
|
+
*/
|
|
212
|
+
declare function optimize(input: string, options?: NormalizeOptions): string;
|
|
213
|
+
/**
|
|
214
|
+
* Re-emit input in its own (auto-detected) format at full mode (all keys).
|
|
215
|
+
* Aliased as {@link expand}.
|
|
216
|
+
*/
|
|
217
|
+
declare function fullize(input: string, options?: NormalizeOptions): string;
|
|
218
|
+
/** Alias of {@link fullize}. */
|
|
219
|
+
declare const expand: typeof fullize;
|
|
220
|
+
/**
|
|
221
|
+
* Re-emit input in its own (auto-detected) format in canonical form.
|
|
222
|
+
*/
|
|
223
|
+
declare function canonicalize(input: string, options?: NormalizeOptions): string;
|
|
224
|
+
/**
|
|
225
|
+
* Count the bits in `input`, auto-detecting bitmark vs JSON.
|
|
226
|
+
*
|
|
227
|
+
* @throws If the input cannot be parsed.
|
|
228
|
+
*/
|
|
229
|
+
declare function countBits(input: string): number;
|
|
230
|
+
/**
|
|
231
|
+
* Split a bitmark document into per-bit source slices.
|
|
232
|
+
*
|
|
233
|
+
* @returns Array of `{ index, byteStart, byteEnd, source }`.
|
|
234
|
+
*/
|
|
235
|
+
declare function splitBits(input: string): BitSlice[];
|
|
236
|
+
/**
|
|
237
|
+
* Transform a document bit-by-bit: apply an optional static `patch` and/or
|
|
238
|
+
* per-bit `preHook`/`postHook`, then re-emit.
|
|
239
|
+
*
|
|
240
|
+
* With neither hook, the whole document is transformed in a single WASM pass
|
|
241
|
+
* (the fast path). When a `preHook` or `postHook` is supplied, `transform`
|
|
242
|
+
* drives the bits one at a time on the calling thread — the hook inspects each
|
|
243
|
+
* bit, may return patches / an output-format override / `drop`, and only data
|
|
244
|
+
* crosses into WASM. The patch may be an array of entries or a JSON string.
|
|
245
|
+
*
|
|
246
|
+
* @returns The transformed document, or an `error:`-prefixed string on failure.
|
|
247
|
+
*/
|
|
248
|
+
declare function transform(input: string, options?: TransformOptions): string;
|
|
249
|
+
/**
|
|
250
|
+
* Parallel counterpart of {@link transform} (Node only). Fans the per-bit WASM
|
|
251
|
+
* compute across a `worker_threads` pool (`options.workers`, default `4`),
|
|
252
|
+
* while `preHook`/`postHook` still run on the calling thread. Output is
|
|
253
|
+
* identical to {@link transform}; this trades startup cost for throughput on
|
|
254
|
+
* large documents.
|
|
255
|
+
*
|
|
256
|
+
* @returns A Promise of the transformed document, or an `error:`-prefixed
|
|
257
|
+
* string on failure.
|
|
258
|
+
*/
|
|
259
|
+
declare function transformParallel(input: string, options?: TransformOptions): Promise<string>;
|
|
100
260
|
/**
|
|
101
261
|
* Breakscape text (escape bitmark special characters).
|
|
102
262
|
*
|
|
@@ -123,9 +283,12 @@ declare function info(options?: InfoOptions): string;
|
|
|
123
283
|
/**
|
|
124
284
|
* Generate bitmark text from a JSON AST.
|
|
125
285
|
*
|
|
126
|
-
*
|
|
127
|
-
*
|
|
286
|
+
* The reverse pipeline: `JSON → json_to_ast → AST → ast_to_bitmark`.
|
|
287
|
+
*
|
|
288
|
+
* @param input - JSON string of the parsed bit entries (forward output shape).
|
|
289
|
+
* @param options - Generate options (e.g. `{ mode: "full" }`).
|
|
290
|
+
* @returns Bitmark text. On failure, an `error:`-prefixed string.
|
|
128
291
|
*/
|
|
129
|
-
declare function generate(
|
|
292
|
+
declare function generate(input: string, options?: ParseOptions): string;
|
|
130
293
|
|
|
131
|
-
export { type BreakscapeOptions, type ConvertOptions, type InfoFormat, type InfoOptions, type InfoType, type LexOptions, type LexStage, type OutputMode, type ParseOptions, type TextFormat, type TextLocation, breakscapeText, convert, generate, info, lex, parse, unbreakscapeText, version };
|
|
294
|
+
export { type BitSlice, type BitView, type BreakscapeOptions, type ConvertOptions, type InfoFormat, type InfoOptions, type InfoType, type InputFormat, type LexOptions, type LexStage, type NormalizeOptions, type OutputFormat, type OutputMode, type ParseOptions, type PatchEntry, type PatchOp, type PostHook, type PreHook, type PreHookResult, type TextFormat, type TextLocation, type TransformOptions, breakscapeText, canonicalize, convert, countBits, expand, fullize, generate, info, lex, optimize, parse, splitBits, transform, transformParallel, unbreakscapeText, version };
|
package/dist/index.js
CHANGED
|
@@ -4,12 +4,206 @@ import { createRequire } from "module";
|
|
|
4
4
|
// src/generated/package_info.ts
|
|
5
5
|
var PACKAGE_INFO = {
|
|
6
6
|
"name": "@gmb/bitmark-parser",
|
|
7
|
-
"version": "6.0
|
|
7
|
+
"version": "6.1.0",
|
|
8
8
|
"author": "Get More Brain Ltd <info@getmorebrain.com>",
|
|
9
9
|
"license": "ISC",
|
|
10
10
|
"description": "A parser for bitmark text, powered by WebAssembly."
|
|
11
11
|
};
|
|
12
12
|
|
|
13
|
+
// src/core/hooked-transform.ts
|
|
14
|
+
function isError(s) {
|
|
15
|
+
return s.startsWith("error:");
|
|
16
|
+
}
|
|
17
|
+
function errorString(e) {
|
|
18
|
+
const m = e instanceof Error ? e.message : String(e);
|
|
19
|
+
return m.startsWith("error:") ? m : `error: ${m}`;
|
|
20
|
+
}
|
|
21
|
+
function stripArray(doc) {
|
|
22
|
+
const t = doc.trim();
|
|
23
|
+
return t.startsWith("[") && t.endsWith("]") ? t.slice(1, -1) : doc;
|
|
24
|
+
}
|
|
25
|
+
function normalisePatch(patch) {
|
|
26
|
+
if (patch === void 0) return [];
|
|
27
|
+
if (typeof patch === "string") {
|
|
28
|
+
const trimmed = patch.trim();
|
|
29
|
+
return trimmed === "" ? [] : JSON.parse(trimmed);
|
|
30
|
+
}
|
|
31
|
+
return patch;
|
|
32
|
+
}
|
|
33
|
+
function buildUnits(wasm2, input, inputIsBitmark) {
|
|
34
|
+
if (inputIsBitmark) {
|
|
35
|
+
const out2 = wasm2.split_bits(input);
|
|
36
|
+
if (isError(out2)) throw new Error(out2);
|
|
37
|
+
const slices = JSON.parse(out2);
|
|
38
|
+
return slices.map((s) => ({
|
|
39
|
+
view: { format: "bitmark", index: s.index, total: slices.length, source: s.source },
|
|
40
|
+
source: s.source
|
|
41
|
+
}));
|
|
42
|
+
}
|
|
43
|
+
const out = wasm2.split_json_bits(input);
|
|
44
|
+
if (isError(out)) throw new Error(out);
|
|
45
|
+
const envelopes = JSON.parse(out);
|
|
46
|
+
return envelopes.map((env, index) => ({
|
|
47
|
+
view: { format: "json", index, total: envelopes.length, bit: env.bit },
|
|
48
|
+
// Per-bit transform consumes a one-bit JSON document.
|
|
49
|
+
source: JSON.stringify([env])
|
|
50
|
+
}));
|
|
51
|
+
}
|
|
52
|
+
function planTransform(wasm2, input, options) {
|
|
53
|
+
const mode = options.mode ?? "optimized";
|
|
54
|
+
const output = options.outputFormat ?? "json";
|
|
55
|
+
const spacesAroundValues = options.spacesAroundValues ?? 1;
|
|
56
|
+
const indent = options.indent ?? 2;
|
|
57
|
+
const pretty = options.pretty ?? false;
|
|
58
|
+
const sel = options.inputFormat ?? "auto";
|
|
59
|
+
const inputIsBitmark = sel === "bitmark" || sel !== "json" && wasm2.is_bitmark(input);
|
|
60
|
+
const inputFormat = inputIsBitmark ? "bitmark" : "json";
|
|
61
|
+
const staticPatch = normalisePatch(options.patch);
|
|
62
|
+
const units = buildUnits(wasm2, input, inputIsBitmark);
|
|
63
|
+
const total = units.length;
|
|
64
|
+
const jobs = [];
|
|
65
|
+
const views = [];
|
|
66
|
+
for (let index = 0; index < total; index++) {
|
|
67
|
+
const { view, source } = units[index];
|
|
68
|
+
view.index = index;
|
|
69
|
+
view.total = total;
|
|
70
|
+
const result = options.preHook ? options.preHook(view) || {} : {};
|
|
71
|
+
if (result.drop) continue;
|
|
72
|
+
const patches = result.patches ? [...staticPatch, ...result.patches] : staticPatch;
|
|
73
|
+
jobs.push({
|
|
74
|
+
index,
|
|
75
|
+
source,
|
|
76
|
+
inputFormat,
|
|
77
|
+
outputFormat: result.outputFormat ?? output,
|
|
78
|
+
mode,
|
|
79
|
+
patchJson: JSON.stringify(patches),
|
|
80
|
+
spacesAroundValues
|
|
81
|
+
});
|
|
82
|
+
views.push(view);
|
|
83
|
+
}
|
|
84
|
+
return { jobs, views, output, pretty, indent };
|
|
85
|
+
}
|
|
86
|
+
function computeBit(wasm2, job) {
|
|
87
|
+
const out = wasm2.transform(
|
|
88
|
+
job.source,
|
|
89
|
+
job.inputFormat,
|
|
90
|
+
job.outputFormat,
|
|
91
|
+
job.mode,
|
|
92
|
+
job.patchJson,
|
|
93
|
+
false,
|
|
94
|
+
2,
|
|
95
|
+
job.spacesAroundValues
|
|
96
|
+
);
|
|
97
|
+
if (isError(out)) return out;
|
|
98
|
+
return job.outputFormat === "json" ? stripArray(out) : out;
|
|
99
|
+
}
|
|
100
|
+
function recombine(wasm2, elements, output, pretty, indent) {
|
|
101
|
+
if (output === "bitmark") return elements.join("\n");
|
|
102
|
+
const arr = `[${elements.join(",")}]`;
|
|
103
|
+
return pretty ? wasm2.prettify(arr, indent) : arr;
|
|
104
|
+
}
|
|
105
|
+
function runHookedTransform(wasm2, input, options) {
|
|
106
|
+
let plan;
|
|
107
|
+
try {
|
|
108
|
+
plan = planTransform(wasm2, input, options);
|
|
109
|
+
} catch (e) {
|
|
110
|
+
return errorString(e);
|
|
111
|
+
}
|
|
112
|
+
const rendered = [];
|
|
113
|
+
for (let i = 0; i < plan.jobs.length; i++) {
|
|
114
|
+
const element = computeBit(wasm2, plan.jobs[i]);
|
|
115
|
+
if (isError(element)) return element;
|
|
116
|
+
options.postHook?.(plan.views[i], element);
|
|
117
|
+
rendered.push(element);
|
|
118
|
+
}
|
|
119
|
+
return recombine(wasm2, rendered, plan.output, plan.pretty, plan.indent);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// src/core/parallel.ts
|
|
123
|
+
async function orchestrateParallel(wasm2, input, options, runJobs) {
|
|
124
|
+
let plan;
|
|
125
|
+
try {
|
|
126
|
+
plan = planTransform(wasm2, input, options);
|
|
127
|
+
} catch (e) {
|
|
128
|
+
return errorString(e);
|
|
129
|
+
}
|
|
130
|
+
let elements;
|
|
131
|
+
try {
|
|
132
|
+
elements = await runJobs(plan.jobs, options.workers ?? 4);
|
|
133
|
+
} catch (e) {
|
|
134
|
+
return errorString(e);
|
|
135
|
+
}
|
|
136
|
+
for (let i = 0; i < elements.length; i++) {
|
|
137
|
+
if (isError(elements[i])) return elements[i];
|
|
138
|
+
options.postHook?.(plan.views[i], elements[i]);
|
|
139
|
+
}
|
|
140
|
+
return recombine(wasm2, elements, plan.output, plan.pretty, plan.indent);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// src/node/pool.ts
|
|
144
|
+
import { fileURLToPath } from "url";
|
|
145
|
+
import { Worker } from "worker_threads";
|
|
146
|
+
function workerPath() {
|
|
147
|
+
return fileURLToPath(new URL("./worker-entry.cjs", import.meta.url));
|
|
148
|
+
}
|
|
149
|
+
function runJobsParallel(jobs, workers) {
|
|
150
|
+
if (jobs.length === 0) return Promise.resolve([]);
|
|
151
|
+
const poolSize = Math.max(1, Math.min(workers, jobs.length));
|
|
152
|
+
const path = workerPath();
|
|
153
|
+
return new Promise((resolve, reject) => {
|
|
154
|
+
const results = new Array(jobs.length);
|
|
155
|
+
let next = 0;
|
|
156
|
+
let settled = 0;
|
|
157
|
+
let done = false;
|
|
158
|
+
const pool = [];
|
|
159
|
+
const shutdown = () => {
|
|
160
|
+
for (const w of pool) void w.terminate();
|
|
161
|
+
};
|
|
162
|
+
const fail = (err) => {
|
|
163
|
+
if (done) return;
|
|
164
|
+
done = true;
|
|
165
|
+
shutdown();
|
|
166
|
+
reject(err);
|
|
167
|
+
};
|
|
168
|
+
const dispatch = (w) => {
|
|
169
|
+
if (done) return;
|
|
170
|
+
if (next >= jobs.length) return;
|
|
171
|
+
const id = next++;
|
|
172
|
+
w.postMessage({ id, job: jobs[id] });
|
|
173
|
+
};
|
|
174
|
+
for (let i = 0; i < poolSize; i++) {
|
|
175
|
+
const w = new Worker(path);
|
|
176
|
+
pool.push(w);
|
|
177
|
+
w.on("message", (res) => {
|
|
178
|
+
if (done) return;
|
|
179
|
+
if (!res.ok) {
|
|
180
|
+
fail(new Error(res.error ?? "worker job failed"));
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
results[res.id] = res.element;
|
|
184
|
+
settled++;
|
|
185
|
+
if (settled === jobs.length) {
|
|
186
|
+
done = true;
|
|
187
|
+
shutdown();
|
|
188
|
+
resolve(results);
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
dispatch(w);
|
|
192
|
+
});
|
|
193
|
+
w.on("error", fail);
|
|
194
|
+
w.on("exit", (code) => {
|
|
195
|
+
if (!done && code !== 0) fail(new Error(`worker exited with code ${code}`));
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
for (const w of pool) dispatch(w);
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// src/node/transform-parallel.ts
|
|
203
|
+
function runParallelTransform(wasm2, input, options) {
|
|
204
|
+
return orchestrateParallel(wasm2, input, options, runJobsParallel);
|
|
205
|
+
}
|
|
206
|
+
|
|
13
207
|
// src/index.ts
|
|
14
208
|
var require2 = createRequire(import.meta.url);
|
|
15
209
|
var wasm = require2("../wasm/bitmark_wasm.js");
|
|
@@ -23,7 +217,58 @@ function parse(input, options = {}) {
|
|
|
23
217
|
return wasm.parse(input, options.mode ?? "optimized");
|
|
24
218
|
}
|
|
25
219
|
function convert(input, options = {}) {
|
|
26
|
-
return wasm.convert(
|
|
220
|
+
return wasm.convert(
|
|
221
|
+
input,
|
|
222
|
+
options.inputFormat ?? "auto",
|
|
223
|
+
options.outputFormat ?? "auto",
|
|
224
|
+
options.mode ?? "optimized",
|
|
225
|
+
options.pretty ?? false,
|
|
226
|
+
options.indent ?? 2,
|
|
227
|
+
options.spacesAroundValues ?? 1
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
function optimize(input, options = {}) {
|
|
231
|
+
return wasm.optimize(input, options.pretty ?? false, options.indent ?? 2);
|
|
232
|
+
}
|
|
233
|
+
function fullize(input, options = {}) {
|
|
234
|
+
return wasm.fullize(input, options.pretty ?? false, options.indent ?? 2);
|
|
235
|
+
}
|
|
236
|
+
var expand = fullize;
|
|
237
|
+
function canonicalize(input, options = {}) {
|
|
238
|
+
return wasm.canonicalize(
|
|
239
|
+
input,
|
|
240
|
+
options.mode ?? "optimized",
|
|
241
|
+
options.pretty ?? false,
|
|
242
|
+
options.indent ?? 2,
|
|
243
|
+
options.spacesAroundValues ?? 1
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
function countBits(input) {
|
|
247
|
+
const out = wasm.count_bits(input);
|
|
248
|
+
if (out.startsWith("error:")) throw new Error(out);
|
|
249
|
+
return Number.parseInt(out, 10);
|
|
250
|
+
}
|
|
251
|
+
function splitBits(input) {
|
|
252
|
+
return JSON.parse(wasm.split_bits(input));
|
|
253
|
+
}
|
|
254
|
+
function transform(input, options = {}) {
|
|
255
|
+
if (options.preHook || options.postHook) {
|
|
256
|
+
return runHookedTransform(wasm, input, options);
|
|
257
|
+
}
|
|
258
|
+
const patchJson = options.patch === void 0 ? "" : typeof options.patch === "string" ? options.patch : JSON.stringify(options.patch);
|
|
259
|
+
return wasm.transform(
|
|
260
|
+
input,
|
|
261
|
+
options.inputFormat ?? "auto",
|
|
262
|
+
options.outputFormat ?? "json",
|
|
263
|
+
options.mode ?? "optimized",
|
|
264
|
+
patchJson,
|
|
265
|
+
options.pretty ?? false,
|
|
266
|
+
options.indent ?? 2,
|
|
267
|
+
options.spacesAroundValues ?? 1
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
function transformParallel(input, options = {}) {
|
|
271
|
+
return runParallelTransform(wasm, input, options);
|
|
27
272
|
}
|
|
28
273
|
function breakscapeText(input, options = {}) {
|
|
29
274
|
const format = options.format ?? "bitmark++";
|
|
@@ -43,16 +288,24 @@ function info(options = {}) {
|
|
|
43
288
|
const indent = options.indent ?? 2;
|
|
44
289
|
return wasm.info(infoType, format, bit, pretty, indent);
|
|
45
290
|
}
|
|
46
|
-
function generate(
|
|
47
|
-
|
|
291
|
+
function generate(input, options = {}) {
|
|
292
|
+
return wasm.convert(input, "json", "bitmark", options.mode ?? "optimized", false, 2, 1);
|
|
48
293
|
}
|
|
49
294
|
export {
|
|
50
295
|
breakscapeText,
|
|
296
|
+
canonicalize,
|
|
51
297
|
convert,
|
|
298
|
+
countBits,
|
|
299
|
+
expand,
|
|
300
|
+
fullize,
|
|
52
301
|
generate,
|
|
53
302
|
info,
|
|
54
303
|
lex,
|
|
304
|
+
optimize,
|
|
55
305
|
parse,
|
|
306
|
+
splitBits,
|
|
307
|
+
transform,
|
|
308
|
+
transformParallel,
|
|
56
309
|
unbreakscapeText,
|
|
57
310
|
version
|
|
58
311
|
};
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/generated/package_info.ts"],"sourcesContent":["// @zen-component: WASM-TSBindings\n\nimport { createRequire } from \"node:module\";\nimport { PACKAGE_INFO } from \"./generated/package_info.js\";\nimport type { LexOptions, ParseOptions, ConvertOptions, BreakscapeOptions, InfoOptions } from \"./types.js\";\nconst require = createRequire(import.meta.url);\nconst wasm = require(\"../wasm/bitmark_wasm.js\") as typeof import(\"../wasm/bitmark_wasm.js\");\n\nexport type { LexOptions, LexStage, ParseOptions, ConvertOptions, OutputMode, BreakscapeOptions, TextFormat, TextLocation, InfoOptions, InfoType, InfoFormat } from \"./types.js\";\n\n/**\n * Get the version of the @gmb/bitmark-parser library.\n *\n * @returns Version string (e.g. \"3.0.0\").\n */\nexport function version(): string {\n return PACKAGE_INFO.version;\n}\n\n/**\n * Lex bitmark input text, returning one line per token.\n *\n * @param input - The bitmark source text.\n * @param options - Lex options (e.g. `{ stage: \"lex\" }`).\n * @returns Token dump string (one token per line).\n */\nexport function lex(input: string, options: LexOptions = {}): string {\n return wasm.lex(input, options.stage ?? \"lex\");\n}\n\n/**\n * Parse bitmark input text and return structured JSON entries.\n *\n * Each entry contains `bit`, `parser`, and `bitmark` fields.\n *\n * @param input - The bitmark source text.\n * @param options - Parse options (e.g. `{ mode: \"full\" }`).\n * @returns JSON string array of structured parsed entries.\n */\nexport function parse(input: string, options: ParseOptions = {}): string {\n return wasm.parse(input, options.mode ?? \"optimized\");\n}\n\n/**\n * Auto-detect input format and convert between bitmark and JSON.\n *\n * @param input - Bitmark or JSON input text.\n * @param options - Convert options (e.g. `{ mode: \"full\", warnings: true }`).\n * @returns Converted output string. For bitmark input, this is a JSON string\n * array of structured parsed entries (`bit`, `parser`, `bitmark`).\n */\nexport function convert(input: string, options: ConvertOptions = {}): string {\n return wasm.convert(input, options.mode ?? \"optimized\", options.warnings ?? false, options.plainText ?? false, options.pretty ?? false, options.indent ?? 2);\n}\n\n/**\n * Breakscape text (escape bitmark special characters).\n *\n * @param input - The text to breakscape.\n * @param options - Breakscape options (e.g. `{ format: \"plainText\", location: \"tag\" }`).\n * @returns Breakscaped text.\n */\nexport function breakscapeText(input: string, options: BreakscapeOptions = {}): string {\n const format = options.format ?? \"bitmark++\";\n const location = options.location ?? \"body\";\n return wasm.breakscape_text(input, format, location);\n}\n\n/**\n * Unbreakscape text (unescape bitmark special characters).\n *\n * @param input - The text to unbreakscape.\n * @param options - Unbreakscape options (e.g. `{ format: \"plainText\", location: \"tag\" }`).\n * @returns Unbreakscaped text.\n */\nexport function unbreakscapeText(input: string, options: BreakscapeOptions = {}): string {\n const format = options.format ?? \"bitmark++\";\n const location = options.location ?? \"body\";\n return wasm.unbreakscape_text(input, format, location);\n}\n\n/**\n * Query information about supported bit types.\n *\n * @param options - Info options (e.g. `{ infoType: \"bit\", format: \"json\", bit: \"cloze\" }`).\n * @returns Information string.\n */\nexport function info(options: InfoOptions = {}): string {\n const infoType = options.infoType ?? \"list\";\n const format = options.format ?? \"text\";\n const bit = options.bit ?? \"\";\n const pretty = options.pretty ?? false;\n const indent = options.indent ?? 2;\n return wasm.info(infoType, format, bit, pretty, indent);\n}\n\n/**\n * Generate bitmark text from a JSON AST.\n *\n * @param _json - JSON string of the AST.\n * @throws Always throws — not yet implemented.\n */\nexport function generate(_json: string): string {\n throw new Error(\"generate is not yet implemented\");\n}\n","// This file is automatically generated. DO NOT EDIT.\n\n/* eslint-disable */\n\nexport const PACKAGE_INFO = {\n \"name\": \"@gmb/bitmark-parser\",\n \"version\": \"6.0.1\",\n \"author\": \"Get More Brain Ltd <info@getmorebrain.com>\",\n \"license\": \"ISC\",\n \"description\": \"A parser for bitmark text, powered by WebAssembly.\"\n};\n"],"mappings":";AAEA,SAAS,qBAAqB;;;ACEvB,IAAM,eAAe;AAAA,EAC1B,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,UAAU;AAAA,EACV,WAAW;AAAA,EACX,eAAe;AACjB;;;ADLA,IAAMA,WAAU,cAAc,YAAY,GAAG;AAC7C,IAAM,OAAOA,SAAQ,yBAAyB;AASvC,SAAS,UAAkB;AAChC,SAAO,aAAa;AACtB;AASO,SAAS,IAAI,OAAe,UAAsB,CAAC,GAAW;AACnE,SAAO,KAAK,IAAI,OAAO,QAAQ,SAAS,KAAK;AAC/C;AAWO,SAAS,MAAM,OAAe,UAAwB,CAAC,GAAW;AACvE,SAAO,KAAK,MAAM,OAAO,QAAQ,QAAQ,WAAW;AACtD;AAUO,SAAS,QAAQ,OAAe,UAA0B,CAAC,GAAW;AAC3E,SAAO,KAAK,QAAQ,OAAO,QAAQ,QAAQ,aAAa,QAAQ,YAAY,OAAO,QAAQ,aAAa,OAAO,QAAQ,UAAU,OAAO,QAAQ,UAAU,CAAC;AAC7J;AASO,SAAS,eAAe,OAAe,UAA6B,CAAC,GAAW;AACrF,QAAM,SAAS,QAAQ,UAAU;AACjC,QAAM,WAAW,QAAQ,YAAY;AACrC,SAAO,KAAK,gBAAgB,OAAO,QAAQ,QAAQ;AACrD;AASO,SAAS,iBAAiB,OAAe,UAA6B,CAAC,GAAW;AACvF,QAAM,SAAS,QAAQ,UAAU;AACjC,QAAM,WAAW,QAAQ,YAAY;AACrC,SAAO,KAAK,kBAAkB,OAAO,QAAQ,QAAQ;AACvD;AAQO,SAAS,KAAK,UAAuB,CAAC,GAAW;AACtD,QAAM,WAAW,QAAQ,YAAY;AACrC,QAAM,SAAS,QAAQ,UAAU;AACjC,QAAM,MAAM,QAAQ,OAAO;AAC3B,QAAM,SAAS,QAAQ,UAAU;AACjC,QAAM,SAAS,QAAQ,UAAU;AACjC,SAAO,KAAK,KAAK,UAAU,QAAQ,KAAK,QAAQ,MAAM;AACxD;AAQO,SAAS,SAAS,OAAuB;AAC9C,QAAM,IAAI,MAAM,iCAAiC;AACnD;","names":["require"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/generated/package_info.ts","../src/core/hooked-transform.ts","../src/core/parallel.ts","../src/node/pool.ts","../src/node/transform-parallel.ts"],"sourcesContent":["// @zen-component: WASM-TSBindings\n\nimport { createRequire } from \"node:module\";\nimport { PACKAGE_INFO } from \"./generated/package_info.js\";\nimport { runHookedTransform, type HookedWasm } from \"./core/hooked-transform.js\";\nimport { runParallelTransform } from \"./node/transform-parallel.js\";\nimport type { LexOptions, ParseOptions, ConvertOptions, BreakscapeOptions, InfoOptions, NormalizeOptions, TransformOptions, BitSlice } from \"./types.js\";\nconst require = createRequire(import.meta.url);\nconst wasm = require(\"../wasm/bitmark_wasm.js\") as typeof import(\"../wasm/bitmark_wasm.js\");\n\nexport type { LexOptions, LexStage, ParseOptions, ConvertOptions, OutputMode, BreakscapeOptions, TextFormat, TextLocation, InfoOptions, InfoType, InfoFormat, InputFormat, OutputFormat, NormalizeOptions, TransformOptions, PatchOp, PatchEntry, BitSlice, BitView, PreHook, PostHook, PreHookResult } from \"./types.js\";\n\n/**\n * Get the version of the @gmb/bitmark-parser library.\n *\n * @returns Version string (e.g. \"3.0.0\").\n */\nexport function version(): string {\n return PACKAGE_INFO.version;\n}\n\n/**\n * Lex bitmark input text, returning one line per token.\n *\n * @param input - The bitmark source text.\n * @param options - Lex options (e.g. `{ stage: \"lex\" }`).\n * @returns Token dump string (one token per line).\n */\nexport function lex(input: string, options: LexOptions = {}): string {\n return wasm.lex(input, options.stage ?? \"lex\");\n}\n\n/**\n * Parse bitmark input text and return structured JSON entries.\n *\n * Each entry contains `bit`, `parser`, and `bitmark` fields.\n *\n * @param input - The bitmark source text.\n * @param options - Parse options (e.g. `{ mode: \"full\" }`).\n * @returns JSON string array of structured parsed entries.\n */\nexport function parse(input: string, options: ParseOptions = {}): string {\n return wasm.parse(input, options.mode ?? \"optimized\");\n}\n\n/**\n * Auto-detect input format and convert between bitmark and JSON.\n *\n * @param input - Bitmark or JSON input text.\n * @param options - Convert options (e.g. `{ mode: \"full\", warnings: true }`).\n * @returns Converted output string. For bitmark input, this is a JSON string\n * array of structured parsed entries (`bit`, `parser`, `bitmark`).\n */\nexport function convert(input: string, options: ConvertOptions = {}): string {\n return wasm.convert(\n input,\n options.inputFormat ?? \"auto\",\n options.outputFormat ?? \"auto\",\n options.mode ?? \"optimized\",\n options.pretty ?? false,\n options.indent ?? 2,\n options.spacesAroundValues ?? 1,\n );\n}\n\n/**\n * Re-emit input in its own (auto-detected) format at optimized mode.\n *\n * @param input - Bitmark or JSON input text.\n * @returns Optimized output in the same format as the input.\n */\nexport function optimize(input: string, options: NormalizeOptions = {}): string {\n return wasm.optimize(input, options.pretty ?? false, options.indent ?? 2);\n}\n\n/**\n * Re-emit input in its own (auto-detected) format at full mode (all keys).\n * Aliased as {@link expand}.\n */\nexport function fullize(input: string, options: NormalizeOptions = {}): string {\n return wasm.fullize(input, options.pretty ?? false, options.indent ?? 2);\n}\n\n/** Alias of {@link fullize}. */\nexport const expand = fullize;\n\n/**\n * Re-emit input in its own (auto-detected) format in canonical form.\n */\nexport function canonicalize(input: string, options: NormalizeOptions = {}): string {\n return wasm.canonicalize(\n input,\n options.mode ?? \"optimized\",\n options.pretty ?? false,\n options.indent ?? 2,\n options.spacesAroundValues ?? 1,\n );\n}\n\n/**\n * Count the bits in `input`, auto-detecting bitmark vs JSON.\n *\n * @throws If the input cannot be parsed.\n */\nexport function countBits(input: string): number {\n const out = wasm.count_bits(input);\n if (out.startsWith(\"error:\")) throw new Error(out);\n return Number.parseInt(out, 10);\n}\n\n/**\n * Split a bitmark document into per-bit source slices.\n *\n * @returns Array of `{ index, byteStart, byteEnd, source }`.\n */\nexport function splitBits(input: string): BitSlice[] {\n return JSON.parse(wasm.split_bits(input)) as BitSlice[];\n}\n\n/**\n * Transform a document bit-by-bit: apply an optional static `patch` and/or\n * per-bit `preHook`/`postHook`, then re-emit.\n *\n * With neither hook, the whole document is transformed in a single WASM pass\n * (the fast path). When a `preHook` or `postHook` is supplied, `transform`\n * drives the bits one at a time on the calling thread — the hook inspects each\n * bit, may return patches / an output-format override / `drop`, and only data\n * crosses into WASM. The patch may be an array of entries or a JSON string.\n *\n * @returns The transformed document, or an `error:`-prefixed string on failure.\n */\nexport function transform(input: string, options: TransformOptions = {}): string {\n if (options.preHook || options.postHook) {\n return runHookedTransform(wasm as unknown as HookedWasm, input, options);\n }\n const patchJson =\n options.patch === undefined\n ? \"\"\n : typeof options.patch === \"string\"\n ? options.patch\n : JSON.stringify(options.patch);\n return wasm.transform(\n input,\n options.inputFormat ?? \"auto\",\n options.outputFormat ?? \"json\",\n options.mode ?? \"optimized\",\n patchJson,\n options.pretty ?? false,\n options.indent ?? 2,\n options.spacesAroundValues ?? 1,\n );\n}\n\n/**\n * Parallel counterpart of {@link transform} (Node only). Fans the per-bit WASM\n * compute across a `worker_threads` pool (`options.workers`, default `4`),\n * while `preHook`/`postHook` still run on the calling thread. Output is\n * identical to {@link transform}; this trades startup cost for throughput on\n * large documents.\n *\n * @returns A Promise of the transformed document, or an `error:`-prefixed\n * string on failure.\n */\nexport function transformParallel(input: string, options: TransformOptions = {}): Promise<string> {\n return runParallelTransform(wasm as unknown as HookedWasm, input, options);\n}\n\n/**\n * Breakscape text (escape bitmark special characters).\n *\n * @param input - The text to breakscape.\n * @param options - Breakscape options (e.g. `{ format: \"plainText\", location: \"tag\" }`).\n * @returns Breakscaped text.\n */\nexport function breakscapeText(input: string, options: BreakscapeOptions = {}): string {\n const format = options.format ?? \"bitmark++\";\n const location = options.location ?? \"body\";\n return wasm.breakscape_text(input, format, location);\n}\n\n/**\n * Unbreakscape text (unescape bitmark special characters).\n *\n * @param input - The text to unbreakscape.\n * @param options - Unbreakscape options (e.g. `{ format: \"plainText\", location: \"tag\" }`).\n * @returns Unbreakscaped text.\n */\nexport function unbreakscapeText(input: string, options: BreakscapeOptions = {}): string {\n const format = options.format ?? \"bitmark++\";\n const location = options.location ?? \"body\";\n return wasm.unbreakscape_text(input, format, location);\n}\n\n/**\n * Query information about supported bit types.\n *\n * @param options - Info options (e.g. `{ infoType: \"bit\", format: \"json\", bit: \"cloze\" }`).\n * @returns Information string.\n */\nexport function info(options: InfoOptions = {}): string {\n const infoType = options.infoType ?? \"list\";\n const format = options.format ?? \"text\";\n const bit = options.bit ?? \"\";\n const pretty = options.pretty ?? false;\n const indent = options.indent ?? 2;\n return wasm.info(infoType, format, bit, pretty, indent);\n}\n\n/**\n * Generate bitmark text from a JSON AST.\n *\n * The reverse pipeline: `JSON → json_to_ast → AST → ast_to_bitmark`.\n *\n * @param input - JSON string of the parsed bit entries (forward output shape).\n * @param options - Generate options (e.g. `{ mode: \"full\" }`).\n * @returns Bitmark text. On failure, an `error:`-prefixed string.\n */\nexport function generate(input: string, options: ParseOptions = {}): string {\n return wasm.convert(input, \"json\", \"bitmark\", options.mode ?? \"optimized\", false, 2, 1);\n}\n","// This file is automatically generated. DO NOT EDIT.\n\n/* eslint-disable */\n\nexport const PACKAGE_INFO = {\n \"name\": \"@gmb/bitmark-parser\",\n \"version\": \"6.1.0\",\n \"author\": \"Get More Brain Ltd <info@getmorebrain.com>\",\n \"license\": \"ISC\",\n \"description\": \"A parser for bitmark text, powered by WebAssembly.\"\n};\n","// @zen-component: TS-HookedTransform\n\nimport type { BitView, OutputFormat, PatchEntry, TransformOptions } from \"../types.js\";\n\n/**\n * The minimal WASM surface the per-bit hook driver needs. Both the Node and\n * browser entry points satisfy this with their loaded module.\n */\nexport interface HookedWasm {\n is_bitmark(input: string): boolean;\n split_bits(input: string): string;\n split_json_bits(input: string): string;\n prettify(json: string, indent: number): string;\n transform(\n input: string,\n inputFormat: string,\n outputFormat: string,\n mode: string,\n patchJson: string,\n pretty: boolean,\n indent: number,\n spacesAroundValues: number,\n ): string;\n}\n\n/** A single bit's compute job: data only, safe to ship to a worker thread. */\nexport interface BitJob {\n index: number;\n source: string;\n inputFormat: \"bitmark\" | \"json\";\n outputFormat: OutputFormat;\n mode: string;\n patchJson: string;\n spacesAroundValues: number;\n}\n\n/**\n * The result of running `preHook` over a document's bits: the compute `jobs`\n * for the bits that survived (in document order) and the matching `views`\n * (so `postHook` can be called per surviving bit), plus the document-level\n * recombination settings.\n */\nexport interface TransformPlan {\n jobs: BitJob[];\n views: BitView[];\n output: OutputFormat;\n pretty: boolean;\n indent: number;\n}\n\nexport function isError(s: string): boolean {\n return s.startsWith(\"error:\");\n}\n\n/**\n * Normalise a thrown value to an `error:`-prefixed string, without\n * double-prefixing a message that already carries the prefix (split helpers\n * surface WASM `error:` strings as thrown `Error`s).\n */\nexport function errorString(e: unknown): string {\n const m = e instanceof Error ? e.message : String(e);\n return m.startsWith(\"error:\") ? m : `error: ${m}`;\n}\n\n/** Strip the outer `[ … ]` of a compact one-element JSON array. */\nexport function stripArray(doc: string): string {\n const t = doc.trim();\n return t.startsWith(\"[\") && t.endsWith(\"]\") ? t.slice(1, -1) : doc;\n}\n\nfunction normalisePatch(patch: TransformOptions[\"patch\"]): PatchEntry[] {\n if (patch === undefined) return [];\n if (typeof patch === \"string\") {\n const trimmed = patch.trim();\n return trimmed === \"\" ? [] : (JSON.parse(trimmed) as PatchEntry[]);\n }\n return patch;\n}\n\nfunction buildUnits(\n wasm: HookedWasm,\n input: string,\n inputIsBitmark: boolean,\n): { view: BitView; source: string }[] {\n if (inputIsBitmark) {\n const out = wasm.split_bits(input);\n if (isError(out)) throw new Error(out);\n const slices = JSON.parse(out) as { index: number; source: string }[];\n return slices.map((s) => ({\n view: { format: \"bitmark\", index: s.index, total: slices.length, source: s.source },\n source: s.source,\n }));\n }\n const out = wasm.split_json_bits(input);\n if (isError(out)) throw new Error(out);\n const envelopes = JSON.parse(out) as { bit?: unknown }[];\n return envelopes.map((env, index) => ({\n view: { format: \"json\", index, total: envelopes.length, bit: env.bit },\n // Per-bit transform consumes a one-bit JSON document.\n source: JSON.stringify([env]),\n }));\n}\n\n/**\n * Split the document and run `preHook` (on the calling thread) for each bit,\n * producing the surviving compute jobs + their views. This is the main-thread\n * half shared by the sync and worker-pool drivers — only the resulting\n * data-only {@link BitJob}s ever cross to a worker.\n */\nexport function planTransform(\n wasm: HookedWasm,\n input: string,\n options: TransformOptions,\n): TransformPlan {\n const mode = options.mode ?? \"optimized\";\n const output: OutputFormat = options.outputFormat ?? \"json\";\n const spacesAroundValues = options.spacesAroundValues ?? 1;\n const indent = options.indent ?? 2;\n const pretty = options.pretty ?? false;\n\n const sel = options.inputFormat ?? \"auto\";\n const inputIsBitmark = sel === \"bitmark\" || (sel !== \"json\" && wasm.is_bitmark(input));\n const inputFormat = inputIsBitmark ? \"bitmark\" : \"json\";\n\n const staticPatch = normalisePatch(options.patch);\n const units = buildUnits(wasm, input, inputIsBitmark);\n const total = units.length;\n\n const jobs: BitJob[] = [];\n const views: BitView[] = [];\n for (let index = 0; index < total; index++) {\n const { view, source } = units[index];\n view.index = index;\n view.total = total;\n\n const result = options.preHook ? options.preHook(view) || {} : {};\n if (result.drop) continue;\n\n const patches = result.patches ? [...staticPatch, ...result.patches] : staticPatch;\n jobs.push({\n index,\n source,\n inputFormat,\n outputFormat: result.outputFormat ?? output,\n mode,\n patchJson: JSON.stringify(patches),\n spacesAroundValues,\n });\n views.push(view);\n }\n return { jobs, views, output, pretty, indent };\n}\n\n/**\n * Compute one bit's rendered element synchronously via WASM. The per-bit\n * element is always compact JSON (the document is prettified once on\n * recombination). Returns an `error:`-prefixed string on failure.\n */\nexport function computeBit(wasm: HookedWasm, job: BitJob): string {\n const out = wasm.transform(\n job.source,\n job.inputFormat,\n job.outputFormat,\n job.mode,\n job.patchJson,\n false,\n 2,\n job.spacesAroundValues,\n );\n if (isError(out)) return out;\n return job.outputFormat === \"json\" ? stripArray(out) : out;\n}\n\n/** Recombine per-bit elements into the final document, in document order. */\nexport function recombine(\n wasm: HookedWasm,\n elements: string[],\n output: OutputFormat,\n pretty: boolean,\n indent: number,\n): string {\n if (output === \"bitmark\") return elements.join(\"\\n\");\n const arr = `[${elements.join(\",\")}]`;\n return pretty ? wasm.prettify(arr, indent) : arr;\n}\n\n/**\n * Per-bit transform driver (synchronous, in-process): split the document, run\n * `preHook` for each bit on the calling thread, apply the static patch + any\n * hook patches, re-emit the bit, run `postHook`, then recombine in document\n * order.\n *\n * Hooks run synchronously on the calling thread; only data crosses into WASM.\n * Used when a `preHook`/`postHook` is supplied; the hookless path stays a\n * single `wasm.transform` call. Returns the document, or an `error:`-prefixed\n * string on failure.\n */\nexport function runHookedTransform(\n wasm: HookedWasm,\n input: string,\n options: TransformOptions,\n): string {\n let plan: TransformPlan;\n try {\n plan = planTransform(wasm, input, options);\n } catch (e) {\n return errorString(e);\n }\n\n const rendered: string[] = [];\n for (let i = 0; i < plan.jobs.length; i++) {\n const element = computeBit(wasm, plan.jobs[i]);\n if (isError(element)) return element;\n options.postHook?.(plan.views[i], element);\n rendered.push(element);\n }\n return recombine(wasm, rendered, plan.output, plan.pretty, plan.indent);\n}\n","// @zen-component: TS-ParallelOrchestrator\n\nimport type { TransformOptions } from \"../types.js\";\nimport { type BitJob, errorString, type HookedWasm, isError, planTransform, recombine } from \"./hooked-transform.js\";\n\n/**\n * A platform pool: compute `jobs` across up to `workers` workers, returning the\n * rendered element per job in submission order. Node and browser supply their\n * own (worker_threads / Worker); the orchestration around it is shared.\n */\nexport type RunJobs = (jobs: BitJob[], workers: number) => Promise<string[]>;\n\n/**\n * Shared parallel transform orchestration. The main-thread half — split +\n * `preHook` + recombine + `postHook` — is identical to the sync driver; only\n * the data-only per-bit jobs cross to `runJobs` (the platform pool). Closures\n * (`preHook`/`postHook`) never leave the calling thread.\n *\n * Returns the document, or an `error:`-prefixed string on failure.\n */\nexport async function orchestrateParallel(\n wasm: HookedWasm,\n input: string,\n options: TransformOptions,\n runJobs: RunJobs,\n): Promise<string> {\n let plan;\n try {\n plan = planTransform(wasm, input, options);\n } catch (e) {\n return errorString(e);\n }\n\n let elements: string[];\n try {\n elements = await runJobs(plan.jobs, options.workers ?? 4);\n } catch (e) {\n return errorString(e);\n }\n\n for (let i = 0; i < elements.length; i++) {\n if (isError(elements[i])) return elements[i];\n options.postHook?.(plan.views[i], elements[i]);\n }\n return recombine(wasm, elements, plan.output, plan.pretty, plan.indent);\n}\n","// @zen-component: TS-WorkerPool\n//\n// A fixed-size Node worker_threads pool that computes per-bit transform jobs in\n// parallel. Jobs are dispatched to idle workers; results are matched by id and\n// returned in submission order. The pool is short-lived (created per\n// transformParallel call) and terminated when all jobs settle.\n\nimport { fileURLToPath } from \"node:url\";\nimport { Worker } from \"node:worker_threads\";\nimport type { BitJob } from \"../core/hooked-transform.js\";\n\ninterface JobResult {\n ok: boolean;\n element?: string;\n error?: string;\n}\n\n// The worker entry is emitted as a sibling CJS file in dist/ (see tsup config),\n// so a CJS-format worker runs regardless of how the package itself was loaded.\nfunction workerPath(): string {\n return fileURLToPath(new URL(\"./worker-entry.cjs\", import.meta.url));\n}\n\n/**\n * Run `jobs` across up to `workers` worker threads, returning the rendered\n * element for each job in the **same order** as `jobs`. Rejects on the first\n * worker error or job error.\n */\nexport function runJobsParallel(jobs: BitJob[], workers: number): Promise<string[]> {\n if (jobs.length === 0) return Promise.resolve([]);\n const poolSize = Math.max(1, Math.min(workers, jobs.length));\n const path = workerPath();\n\n return new Promise<string[]>((resolve, reject) => {\n const results = new Array<string>(jobs.length);\n let next = 0;\n let settled = 0;\n let done = false;\n const pool: Worker[] = [];\n\n const shutdown = () => {\n for (const w of pool) void w.terminate();\n };\n const fail = (err: Error) => {\n if (done) return;\n done = true;\n shutdown();\n reject(err);\n };\n\n const dispatch = (w: Worker) => {\n if (done) return;\n if (next >= jobs.length) return; // no more work for this worker\n const id = next++;\n w.postMessage({ id, job: jobs[id] });\n };\n\n for (let i = 0; i < poolSize; i++) {\n const w = new Worker(path);\n pool.push(w);\n w.on(\"message\", (res: JobResult & { id: number }) => {\n if (done) return;\n if (!res.ok) {\n fail(new Error(res.error ?? \"worker job failed\"));\n return;\n }\n results[res.id] = res.element as string;\n settled++;\n if (settled === jobs.length) {\n done = true;\n shutdown();\n resolve(results);\n return;\n }\n dispatch(w);\n });\n w.on(\"error\", fail);\n w.on(\"exit\", (code) => {\n if (!done && code !== 0) fail(new Error(`worker exited with code ${code}`));\n });\n }\n\n // Prime each worker with one job.\n for (const w of pool) dispatch(w);\n });\n}\n","// @zen-component: TS-TransformParallel\n//\n// Node-only parallel transform: the main-thread half (split + preHook +\n// recombine + postHook) is shared with the synchronous driver and the browser\n// pool via orchestrateParallel; only the per-bit WASM compute is fanned out\n// across a worker_threads pool.\n\nimport { orchestrateParallel } from \"../core/parallel.js\";\nimport type { HookedWasm } from \"../core/hooked-transform.js\";\nimport type { TransformOptions } from \"../types.js\";\nimport { runJobsParallel } from \"./pool.js\";\n\n/**\n * Parallel counterpart of `transform` on Node. `preHook`/`postHook` run on the\n * calling thread; only data-only jobs cross to the worker_threads pool.\n */\nexport function runParallelTransform(\n wasm: HookedWasm,\n input: string,\n options: TransformOptions,\n): Promise<string> {\n return orchestrateParallel(wasm, input, options, runJobsParallel);\n}\n"],"mappings":"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","names":["wasm","out","wasm","wasm","require"]}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var module$1 = require('module');
|
|
4
|
+
var worker_threads = require('worker_threads');
|
|
5
|
+
|
|
6
|
+
// ../../node_modules/tsup/assets/cjs_shims.js
|
|
7
|
+
var getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.tagName.toUpperCase() === "SCRIPT" ? document.currentScript.src : new URL("main.js", document.baseURI).href;
|
|
8
|
+
var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
|
|
9
|
+
var require2 = module$1.createRequire(importMetaUrl);
|
|
10
|
+
var wasm = require2("../wasm/bitmark_wasm.js");
|
|
11
|
+
function stripArray(doc) {
|
|
12
|
+
const t = doc.trim();
|
|
13
|
+
return t.startsWith("[") && t.endsWith("]") ? t.slice(1, -1) : doc;
|
|
14
|
+
}
|
|
15
|
+
worker_threads.parentPort?.on("message", (msg) => {
|
|
16
|
+
const { id, job } = msg;
|
|
17
|
+
try {
|
|
18
|
+
const out = wasm.transform(
|
|
19
|
+
job.source,
|
|
20
|
+
job.inputFormat,
|
|
21
|
+
job.outputFormat,
|
|
22
|
+
job.mode,
|
|
23
|
+
job.patchJson,
|
|
24
|
+
false,
|
|
25
|
+
2,
|
|
26
|
+
job.spacesAroundValues
|
|
27
|
+
);
|
|
28
|
+
if (out.startsWith("error:")) {
|
|
29
|
+
worker_threads.parentPort?.postMessage({ id, ok: false, error: out });
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const element = job.outputFormat === "json" ? stripArray(out) : out;
|
|
33
|
+
worker_threads.parentPort?.postMessage({ id, ok: true, element });
|
|
34
|
+
} catch (e) {
|
|
35
|
+
worker_threads.parentPort?.postMessage({ id, ok: false, error: `error: ${String(e)}` });
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
//# sourceMappingURL=worker-entry.cjs.map
|
|
39
|
+
//# sourceMappingURL=worker-entry.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../node_modules/tsup/assets/cjs_shims.js","../src/node/worker-entry.ts"],"names":["require","createRequire","parentPort"],"mappings":";;;;;;AAKA,IAAM,gBAAA,GAAmB,MACvB,OAAO,QAAA,KAAa,WAAA,GAChB,IAAI,GAAA,CAAI,CAAA,KAAA,EAAQ,UAAU,CAAA,CAAE,CAAA,CAAE,IAAA,GAC7B,QAAA,CAAS,aAAA,IAAiB,QAAA,CAAS,aAAA,CAAc,OAAA,CAAQ,WAAA,EAAY,KAAM,QAAA,GAC1E,QAAA,CAAS,aAAA,CAAc,GAAA,GACvB,IAAI,GAAA,CAAI,SAAA,EAAW,QAAA,CAAS,OAAO,CAAA,CAAE,IAAA;AAEtC,IAAM,gCAAgC,gBAAA,EAAiB;ACD9D,IAAMA,QAAAA,GAAUC,uBAAc,aAAe,CAAA;AAE7C,IAAM,IAAA,GAAOD,SAAQ,yBAAyB,CAAA;AAkB9C,SAAS,WAAW,GAAA,EAAqB;AACvC,EAAA,MAAM,CAAA,GAAI,IAAI,IAAA,EAAK;AACnB,EAAA,OAAO,CAAA,CAAE,UAAA,CAAW,GAAG,CAAA,IAAK,CAAA,CAAE,QAAA,CAAS,GAAG,CAAA,GAAI,CAAA,CAAE,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA,GAAI,GAAA;AACjE;AAEAE,yBAAA,EAAY,EAAA,CAAG,SAAA,EAAW,CAAC,GAAA,KAAoB;AAC7C,EAAA,MAAM,EAAE,EAAA,EAAI,GAAA,EAAI,GAAI,GAAA;AACpB,EAAA,IAAI;AACF,IAAA,MAAM,MAAM,IAAA,CAAK,SAAA;AAAA,MACf,GAAA,CAAI,MAAA;AAAA,MACJ,GAAA,CAAI,WAAA;AAAA,MACJ,GAAA,CAAI,YAAA;AAAA,MACJ,GAAA,CAAI,IAAA;AAAA,MACJ,GAAA,CAAI,SAAA;AAAA,MACJ,KAAA;AAAA,MACA,CAAA;AAAA,MACA,GAAA,CAAI;AAAA,KACN;AACA,IAAA,IAAI,GAAA,CAAI,UAAA,CAAW,QAAQ,CAAA,EAAG;AAC5B,MAAAA,yBAAA,EAAY,YAAY,EAAE,EAAA,EAAI,IAAI,KAAA,EAAO,KAAA,EAAO,KAAK,CAAA;AACrD,MAAA;AAAA,IACF;AACA,IAAA,MAAM,UAAU,GAAA,CAAI,YAAA,KAAiB,MAAA,GAAS,UAAA,CAAW,GAAG,CAAA,GAAI,GAAA;AAChE,IAAAA,yBAAA,EAAY,YAAY,EAAE,EAAA,EAAI,EAAA,EAAI,IAAA,EAAM,SAAS,CAAA;AAAA,EACnD,SAAS,CAAA,EAAG;AACV,IAAAA,yBAAA,EAAY,WAAA,CAAY,EAAE,EAAA,EAAI,EAAA,EAAI,KAAA,EAAO,KAAA,EAAO,CAAA,OAAA,EAAU,MAAA,CAAO,CAAC,CAAC,CAAA,CAAA,EAAI,CAAA;AAAA,EACzE;AACF,CAAC,CAAA","file":"worker-entry.cjs","sourcesContent":["// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () => \n typeof document === \"undefined\" \n ? new URL(`file:${__filename}`).href \n : (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT') \n ? document.currentScript.src \n : new URL(\"main.js\", document.baseURI).href;\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","// @zen-component: TS-WorkerEntry\n//\n// Node worker_threads entry for the parallel transform pool. Each worker loads\n// its own WASM instance and computes one bit at a time: it receives a data-only\n// job ({ source, formats, patches }) and returns the rendered element. Hooks\n// (JS closures) never reach here — they run on the main thread.\n\nimport { createRequire } from \"node:module\";\nimport { parentPort } from \"node:worker_threads\";\nimport type { BitJob } from \"../core/hooked-transform.js\";\n\nconst require = createRequire(import.meta.url);\n// Bundled to dist/worker-entry.cjs; the wasm glue sits at <pkg>/wasm/.\nconst wasm = require(\"../wasm/bitmark_wasm.js\") as {\n transform(\n input: string,\n inputFormat: string,\n outputFormat: string,\n mode: string,\n patchJson: string,\n pretty: boolean,\n indent: number,\n spacesAroundValues: number,\n ): string;\n};\n\ninterface JobMessage {\n id: number;\n job: BitJob;\n}\n\nfunction stripArray(doc: string): string {\n const t = doc.trim();\n return t.startsWith(\"[\") && t.endsWith(\"]\") ? t.slice(1, -1) : doc;\n}\n\nparentPort?.on(\"message\", (msg: JobMessage) => {\n const { id, job } = msg;\n try {\n const out = wasm.transform(\n job.source,\n job.inputFormat,\n job.outputFormat,\n job.mode,\n job.patchJson,\n false,\n 2,\n job.spacesAroundValues,\n );\n if (out.startsWith(\"error:\")) {\n parentPort?.postMessage({ id, ok: false, error: out });\n return;\n }\n const element = job.outputFormat === \"json\" ? stripArray(out) : out;\n parentPort?.postMessage({ id, ok: true, element });\n } catch (e) {\n parentPort?.postMessage({ id, ok: false, error: `error: ${String(e)}` });\n }\n});\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gmb/bitmark-parser",
|
|
3
|
-
"version": "6.0
|
|
3
|
+
"version": "6.1.0",
|
|
4
4
|
"description": "A parser for bitmark text, powered by WebAssembly.",
|
|
5
5
|
"author": "Get More Brain Ltd <info@getmorebrain.com>",
|
|
6
6
|
"license": "ISC",
|
|
@@ -56,7 +56,8 @@
|
|
|
56
56
|
"build:wasm": "bash scripts/build-wasm.sh",
|
|
57
57
|
"build:ts": "npm run init && tsup",
|
|
58
58
|
"build": "npm run version:check && npm run build:wasm && npm run build:ts",
|
|
59
|
-
"test": "node test/smoke.mjs && node --test test/cross-validate.mjs && node --test test/cli.test.mjs",
|
|
59
|
+
"test": "node test/smoke.mjs && node --test test/cross-validate.mjs && node --test test/cli.test.mjs && node --test test/unified.test.mjs && node --test test/parallel.test.mjs",
|
|
60
|
+
"test:browser": "bash scripts/run-browser-tests.sh",
|
|
60
61
|
"test:browser-smoke": "bash scripts/launch-browser-smoke.sh",
|
|
61
62
|
"test:browser-perf": "bash scripts/launch-browser-perf.sh",
|
|
62
63
|
"test:cli-perf": "bash scripts/launch-cli-perf.sh",
|