diff --git a/nx/public/plugins/quick-edit/src/selection.js b/nx/public/plugins/quick-edit/src/selection.js index 59829fe47..90b741072 100644 --- a/nx/public/plugins/quick-edit/src/selection.js +++ b/nx/public/plugins/quick-edit/src/selection.js @@ -1,5 +1,5 @@ import { - findBlock, findImageAtProseIndex, pictureSrc, srcPathsMatch, OVERLAY_SELECTOR, + findBlock, findImageAtProseIndex, findTextBlock, pictureSrc, srcPathsMatch, OVERLAY_SELECTOR, } from './dom-index.js'; import { parseIndex, positionBox } from './utils.js'; import { MESSAGE_TYPES } from '../../../../utils/message-types.js'; @@ -70,6 +70,13 @@ function findPictureBySrc(src, proseIndex, root = document) { .find((pic) => srcPathsMatch(pictureSrc(pic), src)) || null; } +function findContentByIndex(proseIndex, root = document) { + if (proseIndex == null) return null; + const el = findTextBlock(proseIndex, root); + const elIndex = parseIndex(el?.getAttribute?.('data-prose-index')); + return elIndex === proseIndex ? el : null; +} + function resolveSelectionElement(node, root) { if (node.anchorType === 'table') { const block = findBlock(node.proseIndex, root); @@ -81,6 +88,9 @@ function resolveSelectionElement(node, root) { || findImageAtProseIndex(node.proseIndex, root) || findPictureBySrc(node.src, node.proseIndex, root); } + if (node.anchorType === 'content') { + return findContentByIndex(node.proseIndex, root); + } return null; } diff --git a/test/nx/public/plugins/quick-edit/selection.test.js b/test/nx/public/plugins/quick-edit/selection.test.js index 223cdf009..617e3483d 100644 --- a/test/nx/public/plugins/quick-edit/selection.test.js +++ b/test/nx/public/plugins/quick-edit/selection.test.js @@ -13,6 +13,7 @@ function buildBody() { + '

a paragraph
' + ''; } @@ -93,6 +94,27 @@ describe('quick-edit selection overlay', () => { expect(overlay.querySelector('.qe-selected-pill')).to.equal(null); }); + it('setSelectedNode draws a content box without a pill', () => { + setSelectedNode({ anchorType: 'content', proseIndex: 71 }); + const overlay = document.getElementById('qe-selection-overlay'); + expect(overlay.querySelector('.qe-selected-box')).to.not.equal(null); + expect(overlay.querySelector('.qe-selected-pill')).to.equal(null); + }); + + it('setSelectedNode ignores a content index that resolves to no element', () => { + setSelectedNode({ anchorType: 'content', proseIndex: 9999 }); + const overlay = document.getElementById('qe-selection-overlay'); + expect(overlay?.querySelector('.qe-selected-box') ?? null).to.equal(null); + }); + + it('scrolls a content node into view when requested', () => { + const el = document.querySelector('[data-prose-index="71"]'); + let scrolled = false; + el.scrollIntoView = () => { scrolled = true; }; + setSelectedNode({ anchorType: 'content', proseIndex: 71 }, document, { scrollIntoView: true }); + expect(scrolled).to.equal(true); + }); + it('setSelectedNode with null clears the overlay', () => { setSelectedNode({ anchorType: 'table', proseIndex: 50 }); setSelectedNode(null);