pycrdt icon indicating copy to clipboard operation
pycrdt copied to clipboard

XmlText.insert_embed() doesn't seem to work

Open jonathon-love opened this issue 10 months ago • 4 comments

Description

Hi,

I'm trying to use pycrdt to interop with a yjs backed lexical editor, however it looks as though the insert_embed() function of the XmlText class does not work.

Reproduce

the following code:

import pycrdt

def print_events(events: list):
    for event in events:
        print(event)

doc = pycrdt.Doc()
xml_frag = pycrdt.XmlFragment()
doc['root'] = xml_frag

xml_frag.observe_deep(print_events)

xml_text = pycrdt.XmlText()
xml_frag.children.append(xml_text)
xml_text.insert(0, 'the fish was delish')

outputs:

{children_changed: True, target: , path: [], delta: [{'insert': [<pycrdt._xml.XmlText object at 0x1036850d0>]}], keys: {}}
{children_changed: None, target: the fish was delish, path: [0], delta: [{'insert': 'the fish was delish'}], keys: {}}

so far so good ... if i continue:

>>> xml_text.insert_embed(0, pycrdt.Map({"__style":"","__type":"text","__mode":0,"__detail":0,"__format":0}))
{children_changed: None, target: undefinedthe fish was delish, path: [0], delta: [{'insert': None}], keys: {}}

and:

>>> xml_text.diff()
[(None, None), ('the fish was delish', None)]

Expected behavior

the reason i expect something different is because lexical does this with yjs, calling .insertEmbed()

https://github.com/facebook/lexical/blob/main/packages/lexical-yjs/src/CollabElementNode.ts#L602

if i perform the same edit with lexical, apply those changes to the pycrdt doc with doc.apply_update(), i get

>>> xml_text.diff()
[(<builtins.Map object at 0x40260f9ad0>, None), ('the fish was delish', None)]

Context

i'm not actually sure if lexical and yjs are actually behaving correctly here ... insertEmbed() doesn't look to be a documented function ... and so i'm inferring all this from behaviour.

with thanks

jonathon-love avatar Jan 19 '25 00:01 jonathon-love

found other people grappling with this

https://github.com/y-crdt/ypy/discussions/143

jonathon-love avatar Jan 20 '25 00:01 jonathon-love

Hmm I think that @ColonelThirtyTwo, @dmonad or @Horusiath can best answer this question.

davidbrochart avatar Jan 20 '25 07:01 davidbrochart

Do we have any more insight into this? A solution would be helpful.

dropmann avatar May 02 '25 04:05 dropmann

A first step could be to convert that example to Rust using Yrs, and see if it behaves differently.

davidbrochart avatar May 07 '25 12:05 davidbrochart

@jonathon-love Do you really want to insert a pycrdt.Map, or just a dict? This seems to work fine:

xml_text.insert_embed(0, {"__style":"","__type":"text","__mode":0,"__detail":0,"__format":0})

davidbrochart avatar Jun 12 '25 12:06 davidbrochart

if i insert a dict, is it represented in the ydoc as a YMap?

if that's a workaround then that could work -- but i'm pretty confident it does need to represented with a YMap in order for lexical to be happy with it.

with thanks

jonathon-love avatar Jun 13 '25 00:06 jonathon-love

if i insert a dict, is it represented in the ydoc as a YMap?

No, it wouldn't be a shared type.

I opened #270 but there are things I'm not sure about. Would you be able to test it?

davidbrochart avatar Jun 13 '25 08:06 davidbrochart

sure. will take a look in the next couple of days.

jonathon-love avatar Jun 13 '25 09:06 jonathon-love

@jonathon-love did you get a chance to try it out?

davidbrochart avatar Jul 23 '25 08:07 davidbrochart

sorry! i'll try soon!

jonathon-love avatar Jul 24 '25 00:07 jonathon-love