mirror of
https://github.com/ueberdosis/tiptap.git
synced 2024-11-23 19:19:03 +08:00
fix(core): getMarkRange match only the current mark of a type #3872 (#5826)
Some checks failed
build / lint (20) (push) Has been cancelled
build / test (20, map[name:Demos/Examples spec:./demos/src/Examples/**/*.spec.{js,ts}]) (push) Has been cancelled
build / test (20, map[name:Demos/Experiments spec:./demos/src/Experiments/**/*.spec.{js,ts}]) (push) Has been cancelled
build / test (20, map[name:Demos/Extensions spec:./demos/src/Extensions/**/*.spec.{js,ts}]) (push) Has been cancelled
build / test (20, map[name:Demos/GuideContent spec:./demos/src/GuideContent/**/*.spec.{js,ts}]) (push) Has been cancelled
build / test (20, map[name:Demos/GuideGettingStarted spec:./demos/src/GuideGettingStarted/**/*.spec.{js,ts}]) (push) Has been cancelled
build / test (20, map[name:Demos/Marks spec:./demos/src/Marks/**/*.spec.{js,ts}]) (push) Has been cancelled
build / test (20, map[name:Demos/Nodes spec:./demos/src/Nodes/**/*.spec.{js,ts}]) (push) Has been cancelled
build / test (20, map[name:Integration spec:./tests/cypress/integration/**/*.spec.{js,ts}]) (push) Has been cancelled
Publish / Release (20) (push) Has been cancelled
build / build (20) (push) Has been cancelled
Some checks failed
build / lint (20) (push) Has been cancelled
build / test (20, map[name:Demos/Examples spec:./demos/src/Examples/**/*.spec.{js,ts}]) (push) Has been cancelled
build / test (20, map[name:Demos/Experiments spec:./demos/src/Experiments/**/*.spec.{js,ts}]) (push) Has been cancelled
build / test (20, map[name:Demos/Extensions spec:./demos/src/Extensions/**/*.spec.{js,ts}]) (push) Has been cancelled
build / test (20, map[name:Demos/GuideContent spec:./demos/src/GuideContent/**/*.spec.{js,ts}]) (push) Has been cancelled
build / test (20, map[name:Demos/GuideGettingStarted spec:./demos/src/GuideGettingStarted/**/*.spec.{js,ts}]) (push) Has been cancelled
build / test (20, map[name:Demos/Marks spec:./demos/src/Marks/**/*.spec.{js,ts}]) (push) Has been cancelled
build / test (20, map[name:Demos/Nodes spec:./demos/src/Nodes/**/*.spec.{js,ts}]) (push) Has been cancelled
build / test (20, map[name:Integration spec:./tests/cypress/integration/**/*.spec.{js,ts}]) (push) Has been cancelled
Publish / Release (20) (push) Has been cancelled
build / build (20) (push) Has been cancelled
This commit is contained in:
parent
d91f774e11
commit
2ea807d1db
5
.changeset/wicked-meals-shop.md
Normal file
5
.changeset/wicked-meals-shop.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tiptap/core": patch
|
||||
---
|
||||
|
||||
getMarkRange would greedily match more content than it should have if it was the same type of mark, now it will match only the mark at the position #3872
|
@ -9,7 +9,14 @@ function findMarkInSet(
|
||||
attributes: Record<string, any> = {},
|
||||
): ProseMirrorMark | undefined {
|
||||
return marks.find(item => {
|
||||
return item.type === type && objectIncludes(item.attrs, attributes)
|
||||
return (
|
||||
item.type === type
|
||||
&& objectIncludes(
|
||||
// Only check equality for the attributes that are provided
|
||||
Object.fromEntries(Object.keys(attributes).map(k => [k, item.attrs[k]])),
|
||||
attributes,
|
||||
)
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
@ -21,10 +28,23 @@ function isMarkInSet(
|
||||
return !!findMarkInSet(marks, type, attributes)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the range of a mark at a resolved position.
|
||||
*/
|
||||
export function getMarkRange(
|
||||
/**
|
||||
* The position to get the mark range for.
|
||||
*/
|
||||
$pos: ResolvedPos,
|
||||
/**
|
||||
* The mark type to get the range for.
|
||||
*/
|
||||
type: MarkType,
|
||||
attributes: Record<string, any> = {},
|
||||
/**
|
||||
* The attributes to match against.
|
||||
* If not provided, only the first mark at the position will be matched.
|
||||
*/
|
||||
attributes?: Record<string, any>,
|
||||
): Range | void {
|
||||
if (!$pos || !type) {
|
||||
return
|
||||
@ -41,6 +61,9 @@ export function getMarkRange(
|
||||
return
|
||||
}
|
||||
|
||||
// Default to only matching against the first mark's attributes
|
||||
attributes = attributes || start.node.marks[0]?.attrs
|
||||
|
||||
// We now know that the cursor is either at the start, middle or end of a text node with the specified mark
|
||||
// so we can look it up on the targeted mark
|
||||
const mark = findMarkInSet([...start.node.marks], type, attributes)
|
||||
@ -54,9 +77,10 @@ export function getMarkRange(
|
||||
let endIndex = startIndex + 1
|
||||
let endPos = startPos + start.node.nodeSize
|
||||
|
||||
findMarkInSet([...start.node.marks], type, attributes)
|
||||
|
||||
while (startIndex > 0 && mark.isInSet($pos.parent.child(startIndex - 1).marks)) {
|
||||
while (
|
||||
startIndex > 0
|
||||
&& isMarkInSet([...$pos.parent.child(startIndex - 1).marks], type, attributes)
|
||||
) {
|
||||
startIndex -= 1
|
||||
startPos -= $pos.parent.child(startIndex).nodeSize
|
||||
}
|
||||
|
@ -140,4 +140,38 @@ describe('getMarkRange', () => {
|
||||
to: 39,
|
||||
})
|
||||
})
|
||||
it('can distinguish mark boundaries', () => {
|
||||
const testDocument = {
|
||||
type: 'doc',
|
||||
content: [
|
||||
{
|
||||
type: 'paragraph',
|
||||
content: [
|
||||
{ type: 'text', text: 'This is a text with a ' },
|
||||
{ type: 'text', text: 'link.', marks: [{ type: 'link', attrs: { href: 'https://tiptap.dev' } }] },
|
||||
{ type: 'text', text: 'another link', marks: [{ type: 'link', attrs: { href: 'https://tiptap.dev/invalid' } }] },
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'paragraph',
|
||||
content: [
|
||||
{ type: 'text', text: 'This is a text without a link.' },
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const doc = Node.fromJSON(schema, testDocument)
|
||||
const $pos = doc.resolve(27)
|
||||
const range = getMarkRange($pos, schema.marks.link, { href: 'https://tiptap.dev' })
|
||||
|
||||
expect(range).to.deep.eq({
|
||||
from: 23,
|
||||
to: 28,
|
||||
})
|
||||
|
||||
const nextRange = getMarkRange(doc.resolve(28), schema.marks.link)
|
||||
|
||||
expect(nextRange).to.deep.eq({ from: 28, to: 40 })
|
||||
})
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user