Merge pull request #4 from schmelczer/asch/better-api
Improve public API & add docs
This commit is contained in:
commit
f0a204b092
68 changed files with 6832 additions and 779 deletions
5
.github/dependabot.yml
vendored
5
.github/dependabot.yml
vendored
|
|
@ -14,3 +14,8 @@ updates:
|
|||
directories: ["**"]
|
||||
schedule:
|
||||
interval: "daily"
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directories: ["/reconcile-js"]
|
||||
schedule:
|
||||
interval: "daily"
|
||||
|
|
|
|||
2
.github/workflows/check.yml
vendored
2
.github/workflows/check.yml
vendored
|
|
@ -40,4 +40,6 @@ jobs:
|
|||
- name: Test
|
||||
run: |
|
||||
cargo test --verbose -- --include-ignored
|
||||
cargo test --features serde
|
||||
cargo test --features wasm
|
||||
wasm-pack test --node --features wasm
|
||||
|
|
|
|||
6
.gitignore
vendored
6
.gitignore
vendored
|
|
@ -3,3 +3,9 @@
|
|||
|
||||
# Rust build folder
|
||||
target
|
||||
|
||||
# Node dependencies
|
||||
node_modules
|
||||
|
||||
# WebPack build output
|
||||
dist
|
||||
|
|
|
|||
13
.vscode/settings.json
vendored
13
.vscode/settings.json
vendored
|
|
@ -1,7 +1,12 @@
|
|||
{
|
||||
"files.exclude": {
|
||||
"**/dist": true,
|
||||
"**/node_modules": true,
|
||||
"**/snapshots": true,
|
||||
}
|
||||
"**/snapshots": true, // cargo-insta outputs
|
||||
"**/node_modules": true, // node.js dependencies
|
||||
"**/dist": true, // webpack build directory
|
||||
"pkg": true, // wasm-pack build directory
|
||||
"target": true, // rust build directory
|
||||
},
|
||||
"rust-analyzer.cargo.features": [
|
||||
"all"
|
||||
]
|
||||
}
|
||||
230
Cargo.lock
generated
230
Cargo.lock
generated
|
|
@ -4,35 +4,41 @@ version = 4
|
|||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.16.0"
|
||||
version = "3.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
|
||||
checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.2"
|
||||
version = "1.2.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f34d93e62b03caf570cccc334cbc6c2fceca82f39211051345108adcba3eebdc"
|
||||
checksum = "d487aa071b5f64da6f19a3e848e3578944b726ee5a4854b82172f02aa876bfdc"
|
||||
dependencies = [
|
||||
"shlex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
|
||||
|
||||
[[package]]
|
||||
name = "console"
|
||||
version = "0.15.8"
|
||||
version = "0.15.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb"
|
||||
checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8"
|
||||
dependencies = [
|
||||
"encode_unicode",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"windows-sys 0.52.0",
|
||||
"once_cell",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -41,7 +47,7 @@ version = "0.1.7"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.1",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
|
|
@ -53,27 +59,27 @@ checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
|
|||
|
||||
[[package]]
|
||||
name = "encode_unicode"
|
||||
version = "0.3.6"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
|
||||
checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0"
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.1"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.15.2"
|
||||
version = "0.15.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
|
||||
checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.7.0"
|
||||
version = "2.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f"
|
||||
checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
|
|
@ -81,50 +87,36 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "insta"
|
||||
version = "1.42.2"
|
||||
version = "1.43.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50259abbaa67d11d2bcafc7ba1d094ed7a0c70e3ce893f0d0997f73558cb3084"
|
||||
checksum = "154934ea70c58054b556dd430b99a98c2a7ff5309ac9891597e339b5c28f4371"
|
||||
dependencies = [
|
||||
"console",
|
||||
"linked-hash-map",
|
||||
"once_cell",
|
||||
"pin-project",
|
||||
"similar",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.14"
|
||||
version = "1.0.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
|
||||
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.76"
|
||||
version = "0.3.77"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7"
|
||||
checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.171"
|
||||
version = "0.2.174"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6"
|
||||
|
||||
[[package]]
|
||||
name = "linked-hash-map"
|
||||
version = "0.5.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
|
||||
checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
|
|
@ -132,6 +124,12 @@ version = "0.4.27"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
|
||||
|
||||
[[package]]
|
||||
name = "memory_units"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3"
|
||||
|
||||
[[package]]
|
||||
name = "minicov"
|
||||
version = "0.3.7"
|
||||
|
|
@ -144,29 +142,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.20.2"
|
||||
version = "1.21.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
|
||||
|
||||
[[package]]
|
||||
name = "pin-project"
|
||||
version = "1.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a"
|
||||
dependencies = [
|
||||
"pin-project-internal",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-internal"
|
||||
version = "1.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||
|
||||
[[package]]
|
||||
name = "pretty_assertions"
|
||||
|
|
@ -180,18 +158,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.92"
|
||||
version = "1.0.95"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
|
||||
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.37"
|
||||
version = "1.0.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
|
||||
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
|
@ -200,6 +178,7 @@ dependencies = [
|
|||
name = "reconcile"
|
||||
version = "0.4.0"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.1",
|
||||
"console_error_panic_hook",
|
||||
"insta",
|
||||
"pretty_assertions",
|
||||
|
|
@ -208,13 +187,20 @@ dependencies = [
|
|||
"test-case",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-test",
|
||||
"wee_alloc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.18"
|
||||
name = "rustversion"
|
||||
version = "1.0.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
|
||||
checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
|
|
@ -225,12 +211,6 @@ dependencies = [
|
|||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scoped-tls"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.219"
|
||||
|
|
@ -272,15 +252,15 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
|||
|
||||
[[package]]
|
||||
name = "similar"
|
||||
version = "2.6.0"
|
||||
version = "2.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1de1d4f81173b03af4c0cbed3c898f6bff5b870e4a7f5d6f4057d62a7a4b686e"
|
||||
checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.90"
|
||||
version = "2.0.104"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31"
|
||||
checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
@ -302,7 +282,7 @@ version = "3.3.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "adcb7fd841cd518e279be3d5a3eb0636409487998a4aff22f3de87b81e88384f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.1",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
|
|
@ -322,9 +302,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.14"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
|
||||
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
||||
|
||||
[[package]]
|
||||
name = "unsafe-libyaml"
|
||||
|
|
@ -344,20 +324,21 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.99"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396"
|
||||
checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.1",
|
||||
"once_cell",
|
||||
"rustversion",
|
||||
"wasm-bindgen-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.99"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79"
|
||||
checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
|
|
@ -369,11 +350,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-futures"
|
||||
version = "0.4.49"
|
||||
version = "0.4.50"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38176d9b44ea84e9184eff0bc34cc167ed044f816accfe5922e54d84cf48eca2"
|
||||
checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.1",
|
||||
"js-sys",
|
||||
"once_cell",
|
||||
"wasm-bindgen",
|
||||
|
|
@ -382,9 +363,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.99"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe"
|
||||
checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
|
|
@ -392,9 +373,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.99"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2"
|
||||
checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
@ -405,19 +386,21 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.99"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6"
|
||||
checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-test"
|
||||
version = "0.3.49"
|
||||
version = "0.3.50"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c61d44563646eb934577f2772656c7ad5e9c90fac78aa8013d776fcdaf24625d"
|
||||
checksum = "66c8d5e33ca3b6d9fa3b4676d774c5778031d27a578c2b007f905acf816152c3"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"minicov",
|
||||
"scoped-tls",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"wasm-bindgen-test-macro",
|
||||
|
|
@ -425,9 +408,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-test-macro"
|
||||
version = "0.3.49"
|
||||
version = "0.3.50"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "54171416ce73aa0b9c377b51cc3cb542becee1cd678204812e8392e5b0e4a031"
|
||||
checksum = "17d5042cc5fa009658f9a7333ef24291b1291a25b6382dd68862a7f3b969f69b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
@ -436,31 +419,56 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.76"
|
||||
version = "0.3.77"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04dd7223427d52553d3702c004d3b2fe07c148165faa56313cb00211e31c12bc"
|
||||
checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wee_alloc"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dbb3b5a6b2bb17cb6ad44a2e68a43e8d2722c997da10e928665c72ec6c0a0b8e"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10",
|
||||
"libc",
|
||||
"memory_units",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
||||
dependencies = [
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.52.0"
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
|
|
|
|||
15
Cargo.toml
15
Cargo.toml
|
|
@ -21,10 +21,13 @@ wasm-bindgen = { version = "0.2.99", optional = true }
|
|||
# code size when deploying.
|
||||
console_error_panic_hook = { version = "0.1.7", optional = true }
|
||||
|
||||
wee_alloc = { version = "0.4.2", optional = true }
|
||||
cfg-if = "1.0.1"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
serde = [ "dep:serde" ]
|
||||
wasm = [ "dep:wasm-bindgen"]
|
||||
wasm = [ "dep:wasm-bindgen" ]
|
||||
console_error_panic_hook = [ "dep:console_error_panic_hook" ]
|
||||
|
||||
[dev-dependencies]
|
||||
|
|
@ -39,7 +42,10 @@ wasm-bindgen-test = "0.3.49"
|
|||
codegen-units = 1
|
||||
lto = true
|
||||
opt-level = 3
|
||||
strip="debuginfo" # Keep some info for better panics
|
||||
strip="symbols"
|
||||
|
||||
[package.metadata.wasm-pack.profile.release]
|
||||
wasm-opt = ['-O4', '--enable-bulk-memory']
|
||||
|
||||
[lints.rust]
|
||||
unsafe_code = "forbid"
|
||||
|
|
@ -76,11 +82,6 @@ verbose_file_reads = "warn"
|
|||
|
||||
large_stack_arrays = { level = "allow", priority = 1 } # https://github.com/rust-lang/rust-clippy/issues/13774
|
||||
|
||||
# TODO: fix these
|
||||
cast_possible_truncation = { level = "allow", priority = 1 }
|
||||
cast_sign_loss = { level = "allow", priority = 1 }
|
||||
cast_possible_wrap = { level = "allow", priority = 1 }
|
||||
|
||||
# Silly lints
|
||||
implicit_return = { level = "allow", priority = 1 }
|
||||
question_mark_used = { level = "allow", priority = 1 }
|
||||
|
|
|
|||
170
README.md
170
README.md
|
|
@ -1,54 +1,150 @@
|
|||
# VaultLink self-hosted Obsidian plugin for file syncing
|
||||
# Reconcile: conflict-free 3-way text merging
|
||||
|
||||
[](https://github.com/schmelczer/reconcile/actions/workflows/check.yml)
|
||||
[](https://github.com/schmelczer/reconcile/actions/workflows/gh-pages.yml)
|
||||
|
||||
## Develop
|
||||
> [`diff3`](https://www.gnu.org/software/diffutils/manual/html_node/Invoking-diff3.html) (or `git merge`) but with automatic conflict resolution.
|
||||
|
||||
### Install [nvm](https://github.com/nvm-sh/nvm)
|
||||
Reconcile is a Rust and JavaScript (through WebAssembly) library for merging text without user intervention. It automatically resolves conflicts that would typically require user action in traditional 3-way merge tools.
|
||||
|
||||
- `curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash`
|
||||
Try out the [interactive demo](https://schmelczer.dev/reconcile)!
|
||||
|
||||
TODO: add links for crates and npm
|
||||
|
||||
## Features
|
||||
|
||||
- **Conflict-free output** - No more git conflict markers in the result
|
||||
- **Cursor/selection position tracking** - Automatically updates cursor positions during merging
|
||||
- **Pluggable tokenizer** - Choose between word-level, character-level, or custom tokenization
|
||||
- **Full UTF-8 support** - Handles Unicode text correctly
|
||||
- **WebAssembly support** - Use from JavaScript/TypeScript applications
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Rust
|
||||
|
||||
Add to your `Cargo.toml`:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
reconcile = "0.4"
|
||||
```
|
||||
|
||||
```rust
|
||||
use reconcile::{reconcile, BuiltinTokenizer};
|
||||
|
||||
let parent = "Hello world";
|
||||
let left = "Hello beautiful world";
|
||||
let right = "Hi world";
|
||||
|
||||
let result = reconcile(parent, &left.into(), &right.into(), &*BuiltinTokenizer::Word);
|
||||
assert_eq!(result.apply().text(), "Hi beautiful world");
|
||||
```
|
||||
|
||||
### JavaScript/TypeScript
|
||||
|
||||
```bash
|
||||
npm install reconcile
|
||||
```
|
||||
|
||||
```javascript
|
||||
import { init, reconcile } from "reconcile";
|
||||
|
||||
// Initialize the WASM module (required before first use)
|
||||
await init();
|
||||
|
||||
const parent = "Hello world";
|
||||
const left = "Hello beautiful world";
|
||||
const right = "Hi world";
|
||||
|
||||
const result = reconcile(parent, left, right);
|
||||
console.log(result.text); // "Hi beautiful world"
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### Tokenizers
|
||||
|
||||
Reconcile supports different tokenization strategies:
|
||||
|
||||
- **Word tokenizer** (`BuiltinTokenizer::Word`): Splits text into words (default, recommended for most use cases)
|
||||
- **Character tokenizer** (`BuiltinTokenizer::Character`): Splits text into individual characters (fine-grained merging)
|
||||
- **Custom tokenizer**: Implement your own tokenization logic
|
||||
|
||||
### Cursor Tracking
|
||||
|
||||
Reconcile can automatically update cursor and selection positions during merging:
|
||||
|
||||
```javascript
|
||||
const result = reconcile(
|
||||
"Hello world",
|
||||
{
|
||||
text: "Hello beautiful world",
|
||||
cursors: [{ id: 1, position: 6 }], // After "Hello "
|
||||
},
|
||||
{
|
||||
text: "Hi world",
|
||||
cursors: [{ id: 2, position: 0 }], // At beginning
|
||||
}
|
||||
);
|
||||
|
||||
// Result includes updated cursor positions
|
||||
console.log(result.cursors); // [{ id: 1, position: 3 }, { id: 2, position: 0 }]
|
||||
```
|
||||
|
||||
### History Tracking
|
||||
|
||||
Use `reconcileWithHistory` to get detailed information about the merge process:
|
||||
|
||||
```javascript
|
||||
const result = reconcileWithHistory(parent, left, right);
|
||||
console.log(result.history); // Array of spans with their origins
|
||||
```
|
||||
|
||||
## Algorithm
|
||||
|
||||
The algorithm starts similarly to `diff3`. Its inputs are a **parent** document and two conflicting versions: `left` and `right` which have been created from the parent through any series of concurrent edits.
|
||||
|
||||
1. **Diff calculation**: First, 2-way diffs of (parent & left) and (parent & right) are computed using Myers' algorithm
|
||||
2. **Tokenization**: The text is split into tokens (words, characters, etc.) for granular merging
|
||||
3. **Diff cleaning**: The tokens of the same diff are reordered and merged to end up to maximise patch sizes
|
||||
4. **Operation transformation (OT)**: The resulting edits are weaved together using operational transformation principles, ensuring no changes are lost
|
||||
|
||||
`EditedText` (at least in the Rust library) exposes an implementation of OT. The primary purpose of this library isn't to implement OT but to provide automated text merging, howver, OT happens to provide an easy way of merging the output of Myers' diff. The same result could be achieved through many CRDT implementations as well. However, the merging quality is only as good as the 2-way diffs are. For instance, `reconcile` doesn't support `move` semantics as these are decomposed into an `insert` and `delete` operation by Myers'.
|
||||
|
||||
## Motivation
|
||||
|
||||
Sometimes documents get edited concurrently by multiple users (or the same user from multiple devices) resulting in divergent changes.
|
||||
|
||||
To allow for offline editing, we could use CRDTs or Operational Transformation (OT) to come to a consistent resolution of the competing version. However, this requires capturing all user actions: insertions, deletes, move, copies, and pastes. In some applications, this is trivial if the document can only be edited through an editor that's in our control. But this isn't always the case. Users enjoy composable systems that don't lock them in. For example, one of the unique selling points of Obsidian is to provide an editor experience over a folder of Markdown files leaving the user free to change their technology of choice on a whim.
|
||||
|
||||
This means that files can be edited out-of-channel and the only information a text synchronization system can know is the current content of each tracked file. This is described as Differential Synchronization [1]. This is the same problem as what Git and similar version control systems solve but in a manual way. Although the problem is similar, there's a relevant difference between syncing source code and personal notes: in the case of the former, a semantically incorrect conflict resolution can wreak havoc in a code base, or worse, introduce a correctness bug unnoticed. Text notes are different though, humans are well-equipped to finding the signal in a noisy environment and "bad merges" might result in a clumsy sentence but the reader will likely still understand the gist and can fix it if necessary.
|
||||
|
||||
> There are domains of human text which are less tolerant of mis-merges: for instance, two conflicting changes to a contract could result in a term getting negated in different ways from both sides, resulting in a double-negation, thus unknowingly changing the meaning.
|
||||
|
||||
## Development
|
||||
|
||||
### Prerequisites
|
||||
|
||||
#### Install Node.js
|
||||
|
||||
- Install [nvm](https://github.com/nvm-sh/nvm): `curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash`
|
||||
- `nvm install 22`
|
||||
- `nvm use 22`
|
||||
- Optionally set the system-wide default: `nvm alias default 22`
|
||||
|
||||
### Set up Rust
|
||||
#### Set up Rust
|
||||
|
||||
- Install [`rustup`](https://rustup.rs): `curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh`
|
||||
- Install [`wasm-pack`](https://rustwasm.github.io/wasm-pack/installer): `curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh`
|
||||
- `cargo install cargo-insta sqlx-cli cargo-edit`
|
||||
|
||||
### Install Obsidian on Linux
|
||||
|
||||
```sh
|
||||
apt install flatpak
|
||||
flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
|
||||
flatpak install flathub md.obsidian.Obsidian
|
||||
flatpak run md.obsidian.Obsidian
|
||||
```
|
||||
- `cargo install wasm-pack cargo-insta cargo-edit`
|
||||
|
||||
### Scripts
|
||||
|
||||
#### Update HTTP API TS bindings
|
||||
- **Running tests**: `scripts/test.sh`
|
||||
- **Formatting**: `scripts/lint.sh`
|
||||
- **Building website**: `scripts/dev-website.sh`
|
||||
- **Publishing new version**: `scripts/bump-version.sh patch`
|
||||
|
||||
```sh
|
||||
scripts/update-api-types.sh
|
||||
```
|
||||
TODO: license
|
||||
|
||||
#### Publish new version
|
||||
|
||||
```sh
|
||||
scripts/bump-version.sh patch
|
||||
```
|
||||
|
||||
#### Run E2E tests
|
||||
|
||||
```sh
|
||||
scripts/e2e.sh
|
||||
```
|
||||
|
||||
And to clean up the logs & database files, run `scripts/clean-up.sh`
|
||||
|
||||
## Projects
|
||||
|
||||
- [Sync server](./backend/sync_server/README.md)
|
||||
[1]: https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/35605.pdf
|
||||
|
|
|
|||
3
examples/website/.gitignore
vendored
3
examples/website/.gitignore
vendored
|
|
@ -1,3 +0,0 @@
|
|||
reconcile.js
|
||||
reconcile_bg.wasm
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import init, { mergeTextWithHistory } from "./reconcile.js";
|
||||
import { init, reconcileWithHistory } from "./dist/index.js";
|
||||
|
||||
const originalTextArea = document.getElementById("original");
|
||||
const leftTextArea = document.getElementById("left");
|
||||
|
|
@ -37,16 +37,15 @@ function updateMergedText() {
|
|||
const left = leftTextArea.value;
|
||||
const right = rightTextArea.value;
|
||||
|
||||
const results = mergeTextWithHistory(original, left, right);
|
||||
const results = reconcileWithHistory(original, left, right);
|
||||
|
||||
mergedTextArea.innerHTML = "";
|
||||
|
||||
for (const result of results) {
|
||||
for (const {text, history} of results.history) {
|
||||
const span = document.createElement("span");
|
||||
span.className = result.history();
|
||||
span.textContent = result.text();
|
||||
span.className = history;
|
||||
span.textContent = text;
|
||||
mergedTextArea.appendChild(span);
|
||||
result.free();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
3
reconcile-js/jest.config.js
Normal file
3
reconcile-js/jest.config.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
module.exports = {
|
||||
preset: "ts-jest/presets/js-with-babel-esm"
|
||||
};
|
||||
4905
reconcile-js/package-lock.json
generated
Normal file
4905
reconcile-js/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
24
reconcile-js/package.json
Normal file
24
reconcile-js/package.json
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"name": "reconcile",
|
||||
"version": "0.4.0",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/types/index.d.ts",
|
||||
"files": [
|
||||
"dist/*"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "webpack --mode production",
|
||||
"test": "NODE_OPTIONS=\"$NODE_OPTIONS --experimental-vm-modules\" jest"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^29.5.14",
|
||||
"jest": "^29.7.0",
|
||||
"reconcile": "file:../pkg",
|
||||
"ts-jest": "^29.3.4",
|
||||
"ts-loader": "^9.5.2",
|
||||
"tslib": "2.8.1",
|
||||
"typescript": "5.8.3",
|
||||
"webpack": "^5.99.9",
|
||||
"webpack-cli": "^6.0.1"
|
||||
}
|
||||
}
|
||||
70
reconcile-js/src/index.test.ts
Normal file
70
reconcile-js/src/index.test.ts
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
import { init, reconcile, reconcileWithHistory } from "./index";
|
||||
import * as fs from "fs";
|
||||
|
||||
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();
|
||||
|
||||
expect(reconcile("Hello", "Hello world", "Hi world").text).toEqual(
|
||||
"Hi world"
|
||||
);
|
||||
});
|
||||
|
||||
it("call reconcile with cursors", async () => {
|
||||
await initWasm();
|
||||
|
||||
const result = reconcile(
|
||||
"Hello",
|
||||
{
|
||||
text: "Hello world",
|
||||
cursors: [
|
||||
{
|
||||
id: 3,
|
||||
position: 2,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: "Hi world",
|
||||
cursors: [
|
||||
{
|
||||
id: 4,
|
||||
position: 0,
|
||||
},
|
||||
{ id: 5, position: 3 },
|
||||
],
|
||||
}
|
||||
);
|
||||
|
||||
expect(result.text).toEqual("Hi world");
|
||||
expect(result.cursors).toEqual([
|
||||
{ id: 3, position: 0 },
|
||||
{ id: 4, position: 0 },
|
||||
{ id: 5, position: 3 },
|
||||
]);
|
||||
});
|
||||
|
||||
it("call reconcileWithHistory", async () => {
|
||||
await initWasm();
|
||||
|
||||
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 });
|
||||
}
|
||||
201
reconcile-js/src/index.ts
Normal file
201
reconcile-js/src/index.ts
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
import wasmInit, {
|
||||
CursorPosition as wasmCursorPosition,
|
||||
reconcile as wasmReconcile,
|
||||
TextWithCursors as wasmTextWithCursors,
|
||||
SpanWithHistory as wasmSpanWithHistory,
|
||||
BuiltinTokenizer,
|
||||
reconcileWithHistory as wasmReconcileWithHistory,
|
||||
History,
|
||||
InitInput,
|
||||
} from "reconcile";
|
||||
|
||||
export interface TextWithCursors {
|
||||
/** The document's entire content */
|
||||
text: string;
|
||||
/** List of cursor positions, can be null or undefined if there are no cursors */
|
||||
cursors: null | undefined | CursorPosition[];
|
||||
}
|
||||
|
||||
export interface CursorPosition {
|
||||
/** Unique identifier for the cursor */
|
||||
id: number;
|
||||
/** Character position in the text, 0-based */
|
||||
position: number;
|
||||
}
|
||||
|
||||
export interface TextWithCursorsAndHistory {
|
||||
/** The document's entire content */
|
||||
text: string;
|
||||
/** List of cursor positions, can be null or undefined if there are no cursors */
|
||||
cursors: null | undefined | CursorPosition[];
|
||||
/** List of operations leading to `text` from the 3 ancestors */
|
||||
history: SpanWithHistory[];
|
||||
}
|
||||
|
||||
export interface SpanWithHistory {
|
||||
/** Span of text associated with the historical opearion */
|
||||
text: string;
|
||||
/** Origin of the `text` span */
|
||||
history: History;
|
||||
}
|
||||
|
||||
export type Tokenizer = "Line" | "Word" | "Character";
|
||||
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.
|
||||
*
|
||||
* @param original - The original/base version of the text
|
||||
* @param left - The left version of the text, either as string or TextWithCursors
|
||||
* @param right - The right version of the text, either as string or TextWithCursors
|
||||
* @param tokenizer - The tokenization strategy to use (default: "Word")
|
||||
* @returns The reconciled text with merged cursor positions
|
||||
*/
|
||||
export function reconcile(
|
||||
original: string,
|
||||
left: string | TextWithCursors,
|
||||
right: string | TextWithCursors,
|
||||
tokenizer: BuiltinTokenizer = "Word"
|
||||
): TextWithCursors {
|
||||
if (!isInitialised) {
|
||||
throw new Error(UNINITIALISED_MODULE_ERROR);
|
||||
}
|
||||
|
||||
if (!TOKENIZERS.includes(tokenizer)) {
|
||||
throw new Error(UNSUPPORTED_TOKENIZER_ERROR);
|
||||
}
|
||||
|
||||
const leftCursor = toWasmTextWithCursors(left);
|
||||
const rightCursor = toWasmTextWithCursors(right);
|
||||
|
||||
const result = wasmReconcile(original, leftCursor, rightCursor, tokenizer);
|
||||
|
||||
leftCursor.free();
|
||||
rightCursor.free();
|
||||
|
||||
const jsResult = toTextWithCursors(result);
|
||||
result.free();
|
||||
|
||||
return jsResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges three versions of text and returns the result with historical information.
|
||||
*
|
||||
* Calculating the `history` is somewhat more expensive, otherwise this function behaves like `reconcile`.
|
||||
*
|
||||
* @param original - The original/base version of the text
|
||||
* @param left - The left version of the text, either as string or TextWithCursors
|
||||
* @param right - The right version of the text, either as string or TextWithCursors
|
||||
* @param tokenizer - The tokenization strategy to use (default: "Word")
|
||||
* @returns The reconciled text with cursor positions and history of changes
|
||||
*/
|
||||
export function reconcileWithHistory(
|
||||
original: string,
|
||||
left: string | TextWithCursors,
|
||||
right: string | TextWithCursors,
|
||||
tokenizer: BuiltinTokenizer = "Word"
|
||||
): TextWithCursorsAndHistory {
|
||||
if (!isInitialised) {
|
||||
throw new Error(UNINITIALISED_MODULE_ERROR);
|
||||
}
|
||||
|
||||
if (!TOKENIZERS.includes(tokenizer)) {
|
||||
throw new Error(UNSUPPORTED_TOKENIZER_ERROR);
|
||||
}
|
||||
|
||||
const leftCursor = toWasmTextWithCursors(left);
|
||||
const rightCursor = toWasmTextWithCursors(right);
|
||||
|
||||
const result = wasmReconcileWithHistory(
|
||||
original,
|
||||
leftCursor,
|
||||
rightCursor,
|
||||
tokenizer
|
||||
);
|
||||
|
||||
leftCursor.free();
|
||||
rightCursor.free();
|
||||
|
||||
const jsResult = toTextWithCursors(result);
|
||||
const history = result.history().map(toSpanWithHistory);
|
||||
result.free();
|
||||
|
||||
return {
|
||||
...jsResult,
|
||||
history,
|
||||
};
|
||||
}
|
||||
|
||||
function toWasmTextWithCursors(
|
||||
text: string | TextWithCursors
|
||||
): wasmTextWithCursors {
|
||||
const isInputString = typeof text == "string";
|
||||
const leftText = isInputString ? text : text.text;
|
||||
const leftCursors = isInputString ? [] : text.cursors ?? [];
|
||||
|
||||
return new wasmTextWithCursors(
|
||||
leftText,
|
||||
leftCursors.map(toWasmCursorPosition)
|
||||
);
|
||||
}
|
||||
|
||||
function toWasmCursorPosition({
|
||||
id,
|
||||
position,
|
||||
}: CursorPosition): wasmCursorPosition {
|
||||
return new wasmCursorPosition(id, position);
|
||||
}
|
||||
|
||||
function toTextWithCursors(
|
||||
textWithCursor: wasmTextWithCursors
|
||||
): TextWithCursors {
|
||||
return {
|
||||
text: textWithCursor.text(),
|
||||
cursors: textWithCursor.cursors().map(toCursorPosition),
|
||||
};
|
||||
}
|
||||
|
||||
function toCursorPosition(cursor: wasmCursorPosition): CursorPosition {
|
||||
return {
|
||||
id: cursor.id(),
|
||||
position: cursor.characterIndex(),
|
||||
};
|
||||
}
|
||||
|
||||
function toSpanWithHistory(
|
||||
textWithHistory: wasmSpanWithHistory
|
||||
): SpanWithHistory {
|
||||
return {
|
||||
text: textWithHistory.text(),
|
||||
history: textWithHistory.history(),
|
||||
};
|
||||
}
|
||||
19
reconcile-js/tsconfig.json
Normal file
19
reconcile-js/tsconfig.json
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"module": "ESNext",
|
||||
"target": "ESNext",
|
||||
"strict": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"esModuleInterop": true,
|
||||
"moduleResolution": "bundler",
|
||||
"declaration": true,
|
||||
"declarationDir": "./dist/types",
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src",
|
||||
"skipLibCheck": true,
|
||||
"inlineSourceMap": true
|
||||
},
|
||||
"exclude": [
|
||||
"./dist"
|
||||
]
|
||||
}
|
||||
37
reconcile-js/webpack.config.js
Normal file
37
reconcile-js/webpack.config.js
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
const path = require("path");
|
||||
|
||||
|
||||
module.exports = {
|
||||
entry: "./src/index.ts",
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.ts$/,
|
||||
use: ["ts-loader"]
|
||||
},
|
||||
{
|
||||
test: /\.wasm$/,
|
||||
type: "asset/inline"
|
||||
}
|
||||
]
|
||||
},
|
||||
optimization: {
|
||||
// the consuming project should take care of minification
|
||||
minimize: false
|
||||
},
|
||||
resolve: {
|
||||
extensions: [".ts"],
|
||||
alias: {
|
||||
root: __dirname,
|
||||
src: path.resolve(__dirname, "src")
|
||||
}
|
||||
},
|
||||
output: {
|
||||
path: path.resolve(__dirname, "dist"),
|
||||
filename: "index.js",
|
||||
libraryTarget: "module"
|
||||
},
|
||||
experiments: {
|
||||
outputModule: true
|
||||
},
|
||||
};
|
||||
|
|
@ -2,13 +2,12 @@
|
|||
|
||||
set -e
|
||||
|
||||
rm -rf pkg
|
||||
wasm-pack build --target web --features wasm,wee_alloc
|
||||
cd reconcile-js
|
||||
npm run build
|
||||
mkdir -p ../examples/website/dist
|
||||
cp -R dist/index.js ../examples/website/dist/index.js
|
||||
|
||||
wasm-pack build --target web --features wasm
|
||||
|
||||
cp -R pkg/reconcile.js examples/website/
|
||||
cp -R pkg/reconcile_bg.wasm examples/website/
|
||||
|
||||
cd examples/website/
|
||||
cd ../examples/website
|
||||
|
||||
python3 -m http.server $1 --bind 0.0.0.0
|
||||
|
|
|
|||
8
scripts/lint.sh
Executable file
8
scripts/lint.sh
Executable file
|
|
@ -0,0 +1,8 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
cargo clippy --all-targets --all-features --fix --allow-dirty --allow-staged
|
||||
cargo fmt --all
|
||||
|
||||
echo "Success!"
|
||||
16
scripts/test.sh
Executable file
16
scripts/test.sh
Executable file
|
|
@ -0,0 +1,16 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
wasm-pack build --target web --features wasm,wee_alloc
|
||||
cargo test --verbose
|
||||
cargo test --features serde
|
||||
cargo test --features wasm,wee_alloc
|
||||
wasm-pack test --node --features wasm,wee_alloc
|
||||
|
||||
cd reconcile-js
|
||||
npm install
|
||||
npm run test
|
||||
cd -
|
||||
|
||||
echo "Success!"
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
pub mod myers;
|
||||
pub mod raw_operation;
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue