How to get all link marks in selection?

I’m trying to get all link marks within the selected text.

This is how I am doing it at the moment:

menuItems.push({
  command: (state, dispatch) => {
    const markType = schema.marks.link;

    let { empty, $cursor, ranges } = state.selection;

    if (empty && !$cursor) return false;
    if (dispatch) {
      if (!$cursor) {
        let has = false;
        let tr = state.tr;
        for (let i = 0; !has && i < ranges.length; i++) {
          let { $from, $to } = ranges[i];
          has = state.doc.rangeHasMark($from.pos, $to.pos, markType);
        }
        for (let i = 0; i < ranges.length; i++) {
          let { $from, $to } = ranges[i];
          if (has) {
            const marks = state.doc.resolve($from.pos).marks();
            const linkMarks = marks
              .filter(mark => mark.type.name === 'link');
            if (linkMarks.length && editorViewRef) {
              let linkHrefs = linkMarks.map(linkMark => linkMark.attrs.href);
              linkHrefs = uniqBy(linkHrefs, 'attrs.href');
              const wysiwygRootNode = editorViewRef.dom.closest('.wysiwyg');
              const event = new CustomEvent('wysiwyg:linkRemoved', { detail: { linkHrefs } });
              wysiwygRootNode.dispatchEvent(event);
            }
            tr.removeMark($from.pos, $to.pos, markType);
          }
        }
        dispatch(tr.scrollIntoView());
      }
    }
  },
  dom: icon(unlinkGlyph, 'Unlink', 'unlink'),
});

But its not quite right, as it only returns marks that start where then cursor is.

I’m having a hard time trying to coerce $from and $to into a ResolvedPos so I can call marks() on the range.

What is a good way to find all marks in a selection?

i.e. if the text is

The quick brown fox jumped over the lazy dog

And the highlighted part is

quick brown fox

What should be done to get these two marks?

[http://google.co.uk/, http://google.co.uk/]

1 Like

I’m having a hard time trying to coerce $from and $to into a ResolvedPos

These are ResolvedPos instances, so you don’t have to coerce at all.

But marks is probably not what you want here. nodesBetween should provide an easy way to go through the nodes in a given range, allowing you to check whether they have a link mark and accumulate the ranges that do.

This thread might be helpful too: Best method for collecting all marks in a block?

1 Like