Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions ext/yrb/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,9 @@ fn init() -> Result<(), Error> {
method!(YXmlText::yxml_text_attributes, 1),
)
.expect("cannot define private method: yxml_text_attributes");
yxml_text
.define_private_method("yxml_text_diff", method!(YXmlText::yxml_text_diff, 1))
.expect("cannot define private method: yxml_text_diff");
yxml_text
.define_private_method("yxml_text_format", method!(YXmlText::yxml_text_format, 4))
.expect("cannot define private method: yxml_text_format");
Expand Down
36 changes: 35 additions & 1 deletion ext/yrb/src/yxml_text.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use crate::utils::map_rhash_to_attrs;
use crate::ydiff::YDiff;
use crate::yvalue::YValue;
use crate::yxml_fragment::YXmlFragment;
use crate::{YTransaction, YXmlElement};
use magnus::{Error, IntoValue, RHash, Value};
use magnus::{Error, IntoValue, RHash, Value, RArray};
use std::cell::RefCell;
use yrs::types::text::YChange;
use yrs::{Any, GetString, Text, Xml, XmlNode, XmlTextRef};

#[magnus::wrap(class = "Y::XMLText")]
Expand All @@ -13,6 +15,38 @@ pub(crate) struct YXmlText(pub(crate) RefCell<XmlTextRef>);
unsafe impl Send for YXmlText {}

impl YXmlText {
pub(crate) fn yxml_text_diff(&self, transaction: &YTransaction) -> RArray {
let tx = transaction.transaction();
let tx = tx.as_ref().unwrap();

RArray::from_iter(
self.0
.borrow()
.diff(tx, YChange::identity)
.iter()
.map(move |diff| {
let yvalue = YValue::from(diff.insert.clone());
let insert = yvalue.0.into_inner();
let attributes = diff.attributes.as_ref().map_or_else(
|| None,
|boxed_attrs| {
let attributes = RHash::new();
for (key, value) in boxed_attrs.iter() {
let key = key.to_string();
let value = YValue::from(value.clone()).0.into_inner();
attributes.aset(key, value).expect("cannot add value");
}
Some(attributes)
},
);
YDiff {
ydiff_insert: insert,
ydiff_attrs: attributes,
}
.into_value()
}),
)
}
pub(crate) fn yxml_text_attributes(&self, transaction: &YTransaction) -> RHash {
let tx = transaction.transaction();
let tx = tx.as_ref().unwrap();
Expand Down
15 changes: 15 additions & 0 deletions lib/y/xml.rb
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,15 @@ def detach(subscription_id)
yxml_text_unobserve(subscription_id)
end

# Diff
#
# @return[Array<YDiff>]
def diff
document.current_transaction do |tx|
yxml_text_diff(tx)
end
end

# Format text
#
# @param index [Integer]
Expand Down Expand Up @@ -791,6 +800,12 @@ def can_insert?(value)
#
# @return [Hash]

# @!method yxml_text_diff(tx)
# Returns text changes as list of diffs
#
# @param transaction [Y::Transaction]
# @return [Array<YDiff>]

# @!method yxml_text_format(tx, index, length, attrs)
#
# @param tx [Y::Transaction]
Expand Down
15 changes: 15 additions & 0 deletions spec/y/xml_text_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,21 @@
expect(xml_text.to_s).to eq("Hello, <format>World!</format>")
end

it "get a list of changes" do
doc = Y::Doc.new
xml_text = doc.get_xml_text("my text")

xml_text.insert(0, "Hello, World!", { format: "bold" })
xml_text.insert(13, " From Hannes.", { format: "italic" })

expect(xml_text.diff.map(&:to_h)).to eq([
{ insert: "Hello, World!",
attrs: { "format" => "bold" } },
{ insert: " From Hannes.",
attrs: { "format" => "italic" } }
])
end

it "inserts string at position" do
doc = Y::Doc.new
xml_text = doc.get_xml_text("my xml text")
Expand Down