#crdt #local-first #collaborative-editing

loro

洛罗是一个高性能的 CRDTs 框架。轻松让你的应用实现协作。

10 个版本 (6 个重大更新)

0.16.2 2024 年 5 月 29 日
0.15.4 2024 年 5 月 16 日
0.5.1 2024 年 5 月 6 日
0.5.0 2024 年 4 月 29 日
0.1.0 2022 年 8 月 7 日

#150数据结构

Download history 1/week @ 2024-04-17 136/week @ 2024-04-24 166/week @ 2024-05-01 29/week @ 2024-05-08 211/week @ 2024-05-15 32/week @ 2024-05-22 215/week @ 2024-05-29 66/week @ 2024-06-05 230/week @ 2024-06-12 40/week @ 2024-06-19 4/week @ 2024-06-26 77/week @ 2024-07-03 101/week @ 2024-07-10 46/week @ 2024-07-17 100/week @ 2024-07-24 83/week @ 2024-07-31

每月 389 次下载

MIT 许可证

1.5MB
36K SLoC

洛罗

洛罗是一个提供 Rust 和 JavaScript API 的高性能 CRDTs 框架。

专为本地优先软件设计,它使得应用状态中的协作变得轻松。

PS:版本控制即将推出。时间旅行功能已可通过 https://loro.dev/docs/tutorial/time_travel 访问。

示例

映射/列表/文本

use loro::{LoroDoc, LoroList, LoroText, LoroValue, ToJson};
use serde_json::json;

let doc = LoroDoc::new();
let map = doc.get_map("map");
map.insert("key", "value").unwrap();
map.insert("true", true).unwrap();
map.insert("null", LoroValue::Null).unwrap();
map.insert("deleted", LoroValue::Null).unwrap();
map.delete("deleted").unwrap();
let list = map.insert_container("list", LoroList::new()).unwrap();
list.insert(0, "List").unwrap();
list.insert(1, 9).unwrap();
let text = map.insert_container("text", LoroText::new()).unwrap();
text.insert(0, "Hello world!").unwrap();
assert_eq!(
    doc.get_deep_value().to_json_value(),
    json!({
        "map": {
            "key": "value",
            "true": true,
            "null": null,
            "list": ["List", 9],
            "text": "Hello world!"
        }
    })
);

富文本

use loro::{ExpandType, LoroDoc, ToJson};
use serde_json::json;

let doc = LoroDoc::new();
let text = doc.get_text("text");
text.insert(0, "Hello world!").unwrap();
text.mark(0..5, "bold", true).unwrap();
assert_eq!(
    text.to_delta().to_json_value(),
    json!([
        { "insert": "Hello", "attributes": {"bold": true} },
        { "insert": " world!" },
    ])
);
text.unmark(3..5, "bold").unwrap();
assert_eq!(
    text.to_delta().to_json_value(),
    json!([
          { "insert": "Hel", "attributes": {"bold": true} },
          { "insert": "lo world!" },
    ])
);

同步

use loro::{LoroDoc, ToJson, ExpandType};
use serde_json::json;

let doc = LoroDoc::new();
let text = doc.get_text("text");
text.insert(0, "Hello world!").unwrap();
let bytes = doc.export_from(&Default::default());
let doc_b = LoroDoc::new();
doc_b.import(&bytes).unwrap();
assert_eq!(doc.get_deep_value(), doc_b.get_deep_value());
let text_b = doc_b.get_text("text");
text_b
    .mark(0..5, "bold", true)
    .unwrap();
doc.import(&doc_b.export_from(&doc.oplog_vv())).unwrap();
assert_eq!(
    text.to_delta().to_json_value(),
    json!([
        { "insert": "Hello", "attributes": {"bold": true} },
        { "insert": " world!" },
    ])
);

保存

use loro::LoroDoc;

let doc = LoroDoc::new();
let text = doc.get_text("text");
text.insert(0, "123").unwrap();
let snapshot = doc.export_snapshot();

let new_doc = LoroDoc::new();
new_doc.import(&snapshot).unwrap();
assert_eq!(new_doc.get_deep_value(), doc.get_deep_value());

依赖

~6–13MB
~162K SLoC