Skip to content

Commit

Permalink
apply yjs#63
Browse files Browse the repository at this point in the history
  • Loading branch information
west1636 committed Oct 1, 2024
1 parent 6349748 commit 9b689b2
Showing 1 changed file with 36 additions and 8 deletions.
44 changes: 36 additions & 8 deletions src/plugins/sync-plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -671,7 +671,9 @@ const createNodeFromYElement = (
: { type: 'added' }
}
}
const node = schema.node(el.nodeName, attrs, children)
const marks = attrs.marks && attrs.marks.map(mark => schema.markFromJSON(mark))
delete attrs.marks
const node = schema.node(el.nodeName, attrs, children, marks)
mapping.set(el, node)
return node
} catch (e) {
Expand Down Expand Up @@ -756,6 +758,9 @@ const createTypeFromElementNode = (node, mapping) => {
type.setAttribute(key, val)
}
}
if (node.marks.length) {
type.setAttribute('marks', node.marks.map(mark => mark.toJSON()))
}
type.insert(
0,
normalizePNodeContent(node).map((n) =>
Expand Down Expand Up @@ -794,6 +799,18 @@ const equalAttrs = (pattrs, yattrs) => {
return eq
}

/**
* Compares Prosemirror marks using their serialized `toJSON()` forms.
* https://github.com/ProseMirror/prosemirror-model/blob/master/src/mark.js
*/
const equalMarks = (pmarks, ymarks) => {
if (pmarks.length !== ymarks.length) return false
for (let i = 0; i < pmarks.length; i++) {
if (pmarks[i].type !== ymarks[i].type || !equalAttrs(pmarks[i].attrs, ymarks[i].attrs)) return false
}
return true
}

/**
* @typedef {Array<Array<PModel.Node>|PModel.Node>} NormalizedPNodeContent
*/
Expand Down Expand Up @@ -838,6 +855,8 @@ const equalYTextPText = (ytext, ptexts) => {
}

/**
* Compares ytype with pnode (Prosemirror node) by looking at normalized content, attrs, marks, and children
*
* @param {Y.XmlElement|Y.XmlText|Y.XmlHook} ytype
* @param {any|Array<any>} pnode
*/
Expand All @@ -846,12 +865,18 @@ const equalYTypePNode = (ytype, pnode) => {
ytype instanceof Y.XmlElement && !(pnode instanceof Array) &&
matchNodeName(ytype, pnode)
) {
const normalizedContent = normalizePNodeContent(pnode)
return ytype._length === normalizedContent.length &&
equalAttrs(ytype.getAttributes(), pnode.attrs) &&
ytype.toArray().every((ychild, i) =>
equalYTypePNode(ychild, normalizedContent[i])
)
let normalizedContent = normalizePNodeContent(pnode)
if (normalizedContent.length !== ytype._length) return false
// Exclude `marks` attribute from comparison with `pnode.attrs` if it exists as attribute on ytype.
let yattrs = ytype.getAttributes()
let pattrs = pnode.attrs
delete yattrs.marks
if (!equalAttrs(yattrs, pattrs)) return false
// Serialize `pnode.marks` so it is in the same form as `marks` in ytype.
let ymarks = ytype.getAttribute('marks') || []
let pmarks = pnode.marks.map(mark => mark.toJSON())
if (!equalMarks(ymarks, pmarks)) return false
return ytype.toArray().every((ychild, i) => equalYTypePNode(ychild, normalizedContent[i]))
}
return ytype instanceof Y.XmlText && pnode instanceof Array &&
equalYTextPText(ytype, pnode)
Expand Down Expand Up @@ -980,7 +1005,7 @@ export const updateYFragment = (y, yDomFragment, pNode, mapping) => {
throw new Error('node name mismatch!')
}
mapping.set(yDomFragment, pNode)
// update attributes
// update attributes and marks
if (yDomFragment instanceof Y.XmlElement) {
const yDomAttrs = yDomFragment.getAttributes()
const pAttrs = pNode.attrs
Expand All @@ -999,6 +1024,9 @@ export const updateYFragment = (y, yDomFragment, pNode, mapping) => {
yDomFragment.removeAttribute(key)
}
}
if (pNode.marks.length) {
yDomFragment.setAttribute('marks', pNode.marks.map(mark => mark.toJSON()))
}
}
// update children
const pChildren = normalizePNodeContent(pNode)
Expand Down

0 comments on commit 9b689b2

Please sign in to comment.