diff --git a/README.md b/README.md index cab66f3..82eb088 100644 --- a/README.md +++ b/README.md @@ -59,9 +59,6 @@ Then use in your application: ```javascript import { init, reconcile } from 'reconcile'; -// One-time setup: initialise the WASM module -await init(); - // Same example as above const parent = 'Hello world'; const left = 'Hello beautiful world'; diff --git a/examples/website/index.ts b/examples/website/index.ts index 871496d..2c810c8 100644 --- a/examples/website/index.ts +++ b/examples/website/index.ts @@ -1,4 +1,4 @@ -import { init, reconcileWithHistory } from 'reconcile'; +import { reconcileWithHistory } from 'reconcile'; import type { Tokenizer } from 'reconcile'; import './style.scss'; @@ -13,8 +13,6 @@ const tokenizerRadios = document.querySelectorAll( const sampleText = `The \`reconcile\` Rust library is embedded on this page as a WASM module and powers these text boxes. Experiment with changing the "Original", "First concurrent edit", and "Second concurrent edit" text boxes to see competing changes get merged in real-time within the "Deconflicted result" box. Here, you will see color-coded tokens marking the origin of each token, including ones that got deleted. The result highly depends on the tokenization strategy, for example, deciding how casing or whitespace is taken into account.`; async function main(): Promise { - await init(); - originalTextArea.addEventListener('input', updateMergedText); leftTextArea.addEventListener('input', updateMergedText); rightTextArea.addEventListener('input', updateMergedText); diff --git a/reconcile-js/src/index.test.ts b/reconcile-js/src/index.test.ts index f98714d..fa1e41d 100644 --- a/reconcile-js/src/index.test.ts +++ b/reconcile-js/src/index.test.ts @@ -1,24 +1,11 @@ -import { init, reconcile, reconcileWithHistory } from './index'; -import * as fs from 'fs'; +import { reconcile, reconcileWithHistory } from './index'; describe('reconcile', () => { - it('tries calling functions without init', () => { - expect(() => reconcile('Hello', 'Hello world', 'Hi world')).toThrow(/call init()/); - - expect(() => reconcileWithHistory('Hello', 'Hello world', 'Hi world')).toThrow( - /call init()/ - ); - }); - - it('call reconcile without cursors', async () => { - await initWasm(); - + it('call reconcile without cursors', () => { expect(reconcile('Hello', 'Hello world', 'Hi world').text).toEqual('Hi world'); }); - it('call reconcile with cursors', async () => { - await initWasm(); - + it('call reconcile with cursors', () => { const result = reconcile( 'Hello', { @@ -50,17 +37,10 @@ describe('reconcile', () => { ]); }); - it('call reconcileWithHistory', async () => { - await initWasm(); - + it('call reconcileWithHistory', () => { const result = reconcileWithHistory('Hello', 'Hello world', 'Hi world'); expect(result.text).toEqual('Hi world'); expect(result.history.length).toBeGreaterThan(0); }); }); - -async function initWasm() { - const wasmBin = fs.readFileSync('../pkg/reconcile_bg.wasm'); - await init({ module_or_path: wasmBin }); -} diff --git a/reconcile-js/src/index.ts b/reconcile-js/src/index.ts index 79020a5..a0d488f 100644 --- a/reconcile-js/src/index.ts +++ b/reconcile-js/src/index.ts @@ -6,9 +6,11 @@ import wasmInit, { BuiltinTokenizer, reconcileWithHistory as wasmReconcileWithHistory, History, - InitInput, + initSync, } from 'reconcile'; +import wasm from 'reconcile/reconcile_bg.wasm'; + export interface TextWithCursors { /** The document's entire content */ text: string; @@ -44,32 +46,10 @@ const TOKENIZERS = ['Line', 'Word', 'Character']; let isInitialised = false; -const UNINITIALISED_MODULE_ERROR = - 'Reconcile module has not been initialized. Please call init() before using any other functions.'; - const UNSUPPORTED_TOKENIZER_ERROR = `Unsupported tokenizer. Only ${TOKENIZERS.join( ', ' )} are supported.`; -/** - * Initializes the WASM module for text reconciliation. - * Must be called before using any other functions. - * - * The function is idempotent. - * - * @param content - Optional initialization input for the WASM module during testing. - * @returns Promise that resolves when initialization is complete - */ -export async function init(content?: InitInput) { - if (isInitialised) { - return; - } - - await wasmInit(content); - - isInitialised = true; -} - /** * Merges three versions of text (original, left, right) and cursor positions. * @@ -85,9 +65,7 @@ export function reconcile( right: string | TextWithCursors, tokenizer: BuiltinTokenizer = 'Word' ): TextWithCursors { - if (!isInitialised) { - throw new Error(UNINITIALISED_MODULE_ERROR); - } + init(); if (!TOKENIZERS.includes(tokenizer)) { throw new Error(UNSUPPORTED_TOKENIZER_ERROR); @@ -124,9 +102,7 @@ export function reconcileWithHistory( right: string | TextWithCursors, tokenizer: BuiltinTokenizer = 'Word' ): TextWithCursorsAndHistory { - if (!isInitialised) { - throw new Error(UNINITIALISED_MODULE_ERROR); - } + init(); if (!TOKENIZERS.includes(tokenizer)) { throw new Error(UNSUPPORTED_TOKENIZER_ERROR); @@ -150,6 +126,16 @@ export function reconcileWithHistory( }; } +function init() { + if (isInitialised) { + return; + } + + initSync({ module: (wasm as any).default }); + + isInitialised = true; +} + function toWasmTextWithCursors(text: string | TextWithCursors): wasmTextWithCursors { const isInputString = typeof text == 'string'; const leftText = isInputString ? text : text.text;