Expose undiff to JS
This commit is contained in:
parent
c9c2b775a8
commit
ee6277c13f
5 changed files with 64 additions and 21 deletions
|
|
@ -4,7 +4,8 @@ import {
|
||||||
TextWithCursors as wasmTextWithCursors,
|
TextWithCursors as wasmTextWithCursors,
|
||||||
SpanWithHistory as wasmSpanWithHistory,
|
SpanWithHistory as wasmSpanWithHistory,
|
||||||
reconcileWithHistory as wasmReconcileWithHistory,
|
reconcileWithHistory as wasmReconcileWithHistory,
|
||||||
getCompactDiff as wasmGetCompactDiff,
|
diff as wasmDiff,
|
||||||
|
undiff as wasmUndiff,
|
||||||
initSync,
|
initSync,
|
||||||
} from 'reconcile-text';
|
} from 'reconcile-text';
|
||||||
|
|
||||||
|
|
@ -182,7 +183,8 @@ export function reconcile(
|
||||||
/**
|
/**
|
||||||
* Generates a compact diff representation between an original and changed text.
|
* Generates a compact diff representation between an original and changed text.
|
||||||
*
|
*
|
||||||
* These can be parsed and unpacked using Rust crate's EditedText::from_changes.
|
* These can be parsed and unpacked using the `undiff` function or the Rust crate's EditedText::from_diff.
|
||||||
|
* Cursor positions are omitted from the diff result.
|
||||||
*
|
*
|
||||||
* This function computes the differences between two versions of text and returns
|
* This function computes the differences between two versions of text and returns
|
||||||
* a compact representation of those changes.
|
* a compact representation of those changes.
|
||||||
|
|
@ -192,7 +194,7 @@ export function reconcile(
|
||||||
* @param tokenizer - The tokenisation strategy, which is the same as used in `reconcile`.
|
* @param tokenizer - The tokenisation strategy, which is the same as used in `reconcile`.
|
||||||
* @returns An array representing the compact diff, with inserts as strings and deletes as negative integers.
|
* @returns An array representing the compact diff, with inserts as strings and deletes as negative integers.
|
||||||
*/
|
*/
|
||||||
export function getCompactDiff(
|
export function diff(
|
||||||
original: string,
|
original: string,
|
||||||
changed: string | TextWithOptionalCursors,
|
changed: string | TextWithOptionalCursors,
|
||||||
tokenizer: BuiltinTokenizer = 'Word'
|
tokenizer: BuiltinTokenizer = 'Word'
|
||||||
|
|
@ -205,13 +207,38 @@ export function getCompactDiff(
|
||||||
|
|
||||||
const changedWasm = toWasmTextWithCursors(changed);
|
const changedWasm = toWasmTextWithCursors(changed);
|
||||||
|
|
||||||
const result = wasmGetCompactDiff(original, changedWasm, tokenizer);
|
const result = wasmDiff(original, changedWasm, tokenizer);
|
||||||
|
|
||||||
changedWasm.free();
|
changedWasm.free();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies a compact diff to an original text to reconstruct the changed version.
|
||||||
|
*
|
||||||
|
* This function takes an original text and a compact diff representation (as produced
|
||||||
|
* by the `diff` function) and reconstructs the modified text.
|
||||||
|
*
|
||||||
|
* @param original - The original/base version of the text
|
||||||
|
* @param diff - The compact diff array representing changes (inserts as strings, deletes as negative integers)
|
||||||
|
* @param tokenizer - The tokenisation strategy, which is the same as used in `reconcile`.
|
||||||
|
* @returns The reconstructed changed text as a string.
|
||||||
|
*/
|
||||||
|
export function undiff(
|
||||||
|
original: string,
|
||||||
|
diff: Array<number | string>,
|
||||||
|
tokenizer: BuiltinTokenizer = 'Word'
|
||||||
|
): string {
|
||||||
|
init();
|
||||||
|
|
||||||
|
if (!BUILTIN_TOKENIZERS.includes(tokenizer)) {
|
||||||
|
throw new Error(UNSUPPORTED_TOKENIZER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
return wasmUndiff(original, diff, tokenizer);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Merges three versions of text and returns detailed provenance information.
|
* Merges three versions of text and returns detailed provenance information.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -172,7 +172,7 @@
|
||||||
//! &changes.into()
|
//! &changes.into()
|
||||||
//! );
|
//! );
|
||||||
//!
|
//!
|
||||||
//! let serialized = serde_yaml::to_string(&result.to_changes()).unwrap();
|
//! let serialized = serde_yaml::to_string(&result.to_diff()).unwrap();
|
||||||
//! assert_eq!(
|
//! assert_eq!(
|
||||||
//! serialized,
|
//! serialized,
|
||||||
//! concat!(
|
//! concat!(
|
||||||
|
|
@ -183,7 +183,7 @@
|
||||||
//! );
|
//! );
|
||||||
//!
|
//!
|
||||||
//! let deserialized = serde_yaml::from_str(&serialized).unwrap();
|
//! let deserialized = serde_yaml::from_str(&serialized).unwrap();
|
||||||
//! let reconstructed = EditedText::from_changes(
|
//! let reconstructed = EditedText::from_diff(
|
||||||
//! original,
|
//! original,
|
||||||
//! deserialized,
|
//! deserialized,
|
||||||
//! &*BuiltinTokenizer::Word
|
//! &*BuiltinTokenizer::Word
|
||||||
|
|
|
||||||
34
src/wasm.rs
34
src/wasm.rs
|
|
@ -3,7 +3,7 @@ use core::str;
|
||||||
|
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
use crate::{BuiltinTokenizer, CursorPosition, SpanWithHistory, TextWithCursors};
|
use crate::{BuiltinTokenizer, CursorPosition, EditedText, SpanWithHistory, TextWithCursors};
|
||||||
|
|
||||||
#[global_allocator]
|
#[global_allocator]
|
||||||
static ALLOC: wee_alloc::WeeAlloc<'_> = wee_alloc::WeeAlloc::INIT;
|
static ALLOC: wee_alloc::WeeAlloc<'_> = wee_alloc::WeeAlloc::INIT;
|
||||||
|
|
@ -32,6 +32,7 @@ pub fn reconcile_with_history(
|
||||||
tokenizer: BuiltinTokenizer,
|
tokenizer: BuiltinTokenizer,
|
||||||
) -> TextWithCursorsAndHistory {
|
) -> TextWithCursorsAndHistory {
|
||||||
set_panic_hook();
|
set_panic_hook();
|
||||||
|
|
||||||
let reconciled = crate::reconcile(parent, left, right, &*tokenizer);
|
let reconciled = crate::reconcile(parent, left, right, &*tokenizer);
|
||||||
let text_with_cursors = reconciled.apply();
|
let text_with_cursors = reconciled.apply();
|
||||||
|
|
||||||
|
|
@ -80,22 +81,37 @@ pub fn generic_reconcile(
|
||||||
|
|
||||||
/// WASM wrapper around getting a compact diff representation of two texts as a
|
/// WASM wrapper around getting a compact diff representation of two texts as a
|
||||||
/// list of numbers and strings.
|
/// list of numbers and strings.
|
||||||
#[wasm_bindgen(js_name = getCompactDiff)]
|
#[wasm_bindgen(js_name = diff)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn get_compact_diff(
|
pub fn diff(parent: &str, changed: &TextWithCursors, tokenizer: BuiltinTokenizer) -> Vec<JsValue> {
|
||||||
parent: &str,
|
|
||||||
changed: &TextWithCursors,
|
|
||||||
tokenizer: BuiltinTokenizer,
|
|
||||||
) -> Vec<JsValue> {
|
|
||||||
set_panic_hook();
|
set_panic_hook();
|
||||||
let edited_text = crate::EditedText::from_strings_with_tokenizer(parent, changed, &*tokenizer);
|
|
||||||
|
let edited_text = EditedText::from_strings_with_tokenizer(parent, changed, &*tokenizer);
|
||||||
edited_text
|
edited_text
|
||||||
.to_changes()
|
.to_diff()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(std::convert::Into::into)
|
.map(std::convert::Into::into)
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Inverse of `diff`, applies a compact diff representation to a parent text
|
||||||
|
#[wasm_bindgen(js_name = undiff)]
|
||||||
|
#[must_use]
|
||||||
|
pub fn undiff(parent: &str, diff: Vec<JsValue>, tokenizer: BuiltinTokenizer) -> String {
|
||||||
|
set_panic_hook();
|
||||||
|
|
||||||
|
EditedText::from_diff(
|
||||||
|
parent,
|
||||||
|
diff.into_iter()
|
||||||
|
.map(|js_value| js_value.try_into())
|
||||||
|
.collect::<Result<_, _>>()
|
||||||
|
.expect("Invalid diff format"),
|
||||||
|
&*tokenizer,
|
||||||
|
)
|
||||||
|
.apply()
|
||||||
|
.text()
|
||||||
|
}
|
||||||
|
|
||||||
fn set_panic_hook() {
|
fn set_panic_hook() {
|
||||||
// https://github.com/rustwasm/console_error_panic_hook#readme
|
// https://github.com/rustwasm/console_error_panic_hook#readme
|
||||||
#[cfg(feature = "console_error_panic_hook")]
|
#[cfg(feature = "console_error_panic_hook")]
|
||||||
|
|
|
||||||
|
|
@ -50,16 +50,16 @@ fn test_document_one_way_with_serialisation() {
|
||||||
);
|
);
|
||||||
|
|
||||||
let serialised_left =
|
let serialised_left =
|
||||||
serde_yaml::from_str(&serde_yaml::to_string(&left_operations.to_changes()).unwrap())
|
serde_yaml::from_str(&serde_yaml::to_string(&left_operations.to_diff()).unwrap())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let serialised_right =
|
let serialised_right =
|
||||||
serde_yaml::from_str(&serde_yaml::to_string(&right_operations.to_changes()).unwrap())
|
serde_yaml::from_str(&serde_yaml::to_string(&right_operations.to_diff()).unwrap())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let restored_left_operations =
|
let restored_left_operations =
|
||||||
EditedText::from_changes(&parent, serialised_left, &*BuiltinTokenizer::Word);
|
EditedText::from_diff(&parent, serialised_left, &*BuiltinTokenizer::Word);
|
||||||
let restored_right_operations =
|
let restored_right_operations =
|
||||||
EditedText::from_changes(&parent, serialised_right, &*BuiltinTokenizer::Word);
|
EditedText::from_diff(&parent, serialised_right, &*BuiltinTokenizer::Word);
|
||||||
|
|
||||||
doc.assert_eq_without_cursors(
|
doc.assert_eq_without_cursors(
|
||||||
&restored_left_operations
|
&restored_left_operations
|
||||||
|
|
|
||||||
|
|
@ -56,11 +56,11 @@ fn test_merge_binary() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[wasm_bindgen_test] // JsValue isn't supported outside of wasm
|
#[wasm_bindgen_test] // JsValue isn't supported outside of wasm
|
||||||
fn test_get_compact_diff() {
|
fn test_diff() {
|
||||||
let parent = "hello ";
|
let parent = "hello ";
|
||||||
let changed = "world";
|
let changed = "world";
|
||||||
|
|
||||||
let result = get_compact_diff(parent, &changed.into(), BuiltinTokenizer::Word);
|
let result = diff(parent, &changed.into(), BuiltinTokenizer::Word);
|
||||||
|
|
||||||
assert_eq!(result.len(), 2);
|
assert_eq!(result.len(), 2);
|
||||||
let first: i64 = result[0].clone().try_into().unwrap();
|
let first: i64 = result[0].clone().try_into().unwrap();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue