Skip to content

Commit

Permalink
fix: better merge mark attributes for existing marks, fix #1039
Browse files Browse the repository at this point in the history
  • Loading branch information
philippkuehn committed Apr 23, 2021
1 parent 5e53e44 commit cfd29fa
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 9 deletions.
37 changes: 30 additions & 7 deletions packages/core/src/commands/setMark.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,41 @@ export const setMark: RawCommands['setMark'] = (typeOrName, attributes = {}) =>
const { selection } = tr
const { empty, ranges } = selection
const type = getMarkType(typeOrName, state.schema)
const oldAttributes = getMarkAttributes(state, type)
const newAttributes = {
...oldAttributes,
...attributes,
}

if (dispatch) {
if (empty) {
tr.addStoredMark(type.create(newAttributes))
const oldAttributes = getMarkAttributes(state, type)

tr.addStoredMark(type.create({
...oldAttributes,
...attributes,
}))
} else {
ranges.forEach(range => {
tr.addMark(range.$from.pos, range.$to.pos, type.create(newAttributes))
const from = range.$from.pos
const to = range.$to.pos

state.doc.nodesBetween(from, to, (node, pos) => {
const trimmedFrom = Math.max(pos, from)
const trimmedTo = Math.min(pos + node.nodeSize, to)
const someHasMark = node.marks.find(mark => mark.type === type)

// if there is already a mark of this type
// we know that we have to merge its attributes
// otherwise we add a fresh new mark
if (someHasMark) {
node.marks.forEach(mark => {
if (type === mark.type) {
tr.addMark(trimmedFrom, trimmedTo, type.create({
...mark.attrs,
...attributes,
}))
}
})
} else {
tr.addMark(trimmedFrom, trimmedTo, type.create(attributes))
}
})
})
}
}
Expand Down
10 changes: 8 additions & 2 deletions packages/core/src/commands/updateAttributes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,10 @@ export const updateAttributes: RawCommands['updateAttributes'] = (typeOrName, at

if (dispatch) {
tr.selection.ranges.forEach(range => {
state.doc.nodesBetween(range.$from.pos, range.$to.pos, (node, pos) => {
const from = range.$from.pos
const to = range.$to.pos

state.doc.nodesBetween(from, to, (node, pos) => {
if (nodeType && nodeType === node.type) {
tr.setNodeMarkup(pos, undefined, {
...node.attrs,
Expand All @@ -51,7 +54,10 @@ export const updateAttributes: RawCommands['updateAttributes'] = (typeOrName, at
if (markType && node.marks.length) {
node.marks.forEach(mark => {
if (markType === mark.type) {
tr.addMark(pos, pos + node.nodeSize, markType.create({
const trimmedFrom = Math.max(pos, from)
const trimmedTo = Math.min(pos + node.nodeSize, to)

tr.addMark(trimmedFrom, trimmedTo, markType.create({
...mark.attrs,
...attributes,
}))
Expand Down

0 comments on commit cfd29fa

Please sign in to comment.