Skip to content

fix: keep the node when before() or after() receives the node itself - #351

Open
lprnmns wants to merge 1 commit into
WebReflection:mainfrom
lprnmns:fix-before-after-self
Open

lprnmns wants to merge 1 commit into
WebReflection:mainfrom
lprnmns:fix-before-after-self

Conversation

@lprnmns

@lprnmns lprnmns commented Oct 22, 2026

Copy link
Copy Markdown

Problem

before() and after() drop the node when it's one of their own arguments:

import {parseHTML} from 'linkedom';

const {document} = parseHTML('<div>a<i></i>b</div>');
const div = document.firstChild;
const i = div.querySelector('i');

i.after('x', i);
div.outerHTML;
// linkedom: '<div>ab</div>'         (the <i> and "x" are gone)
// browsers: '<div>ax<i></i>b</div>'

i.before(i, 'x') loses the node the same way. replaceWith() already handles this case.

asFragment() moves every argument into a fragment, which takes node out of its parent. before() then inserts the fragment before node, which is now inside the fragment. after() inserts it before the end of node read after the move.

Fix

This follows the DOM spec's "viable previous sibling" and "viable next sibling" steps. The insertion point is the nearest sibling that isn't one of the arguments, and it's looked up before the arguments are moved. For before(), the reference is that sibling's next sibling, or the parent's first child when there isn't one. For after(), it's the next sibling that isn't moved, or null to append.

Tests

The new assertions in test/html/element.js cover the node itself among the arguments, moving the adjacent sibling, and the case where no viable sibling is left. They fail without the change (Expected: <div>ax<i></i>b</div>, Got instead: <div>ab</div>). I checked every expected string by running the same calls in Chrome. npm test passes, with coverage still at 100% statements/branches/lines (the same as main). cjs/ is regenerated with npm run cjs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant