Skip to content

MD-3007 Fix replaceRange edge cases - #42

Merged
benney merged 7 commits into
mainfrom
feature/md-3007-mos-proxy-fix-replacerange-edge-cases
Nov 6, 2026
Merged

benney merged 7 commits into
mainfrom
feature/md-3007-mos-proxy-fix-replacerange-edge-cases

Conversation

@benney

@benney benney commented Nov 5, 2026 •

Copy link
Copy Markdown
Member

Fixes to the per-element range path:

  • Void elements don't get an onEndTag callback, which saves CPU; output is unchanged
  • A container with no end tag (img, <path/>) is left alone instead of failing the page transform
  • A range starts at the first start marker, so a start marker nested inside it no longer inserts the replacement twice
  • A range applies to the outermost matching container; a nested container is part of its cut

Patch changeset.

`element.onEndTag` throws "No end tag" on HTML void elements. The marker
pass called it on every element under a range container, and the
replacement pass on each fromMarker element, relying on try/catch. Skip
the call for the standard void tags so the runtime no longer raises an
exception per void element.

Only elements in the HTML namespace are void: a `<link>` or `<source>`
inside `<svg>` has an end tag and keeps the old path. An element that
doesn't report its namespace is never treated as void.
A replaceRange selector that matches an element with no end tag (`img`,
or a self-closing SVG element) made onEndTag throw out of the parent
handler and failed the whole page transform. Such an element has no
content to cut, so leave it alone.
A start marker nested inside the first one started the range again: the
replacement went in twice and the rest of the outer marker's content was
cut. An IN_START state now holds the range until the first start marker's
end tag.

A container nested inside another matching one got a range of its own.
A `${selector} ${selector}` handler, registered ahead of the container
handler in both passes, now marks it as part of the outer range.
Copilot AI balanced review requested due to automatic review settings November 5, 2026 10:18
@changeset-bot

changeset-bot Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 95d3573

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@monetizationos/proxy Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Concatenating selectors misidentifies nested containers in both processing passes, causing valid replacements to be skipped or inner containers to start separate ranges.

1 open issue
What changed in this PR

This PR addresses replaceRange edge cases in the proxy’s HTML component transformation pipeline.

Changes:

  • Adds namespace-aware void-element detection to avoid unnecessary end-tag callbacks.
  • Handles containers without end tags and adjusts range handling for nested markers and containers.
  • Adds regression tests and patch changesets.
File Description
test/​stages/​voidElements.spec.ts Tests void elements, namespaces, and containers without end tags.
test/​stages/​surfaceComponents.spec.ts Adds nested marker and container regression tests.
test/​fakes/​LolHtmlRewriter.ts Exposes element namespaces in the test adapter.
src/​stages/​voidElements.ts Adds namespace-aware HTML void-element detection.
src/​stages/​findMarkerPositions.ts Adjusts nested-container discovery and void-element handling.
src/​stages/​buildReplacementHandlers.ts Updates range state, nesting guards, and no-end-tag handling.
src/​adapters/​HtmlRewriterAdapter.ts Adds optional element namespace metadata.
.changeset/​skip-endtag-void-elements.md Documents reduced void-element callback overhead.
.changeset/​range-nested-matches.md Documents nested marker and container behavior.
.changeset/​range-container-no-end-tag.md Documents handling of containers without end tags.

Review effort: Balanced

Comment thread src/stages/findMarkerPositions.ts Resolved
@benney
benney added this pull request to stack #44 November 5, 2026 11:07
Comment thread test/stages/voidElements.spec.ts Resolved
Comment thread test/stages/voidElements.spec.ts Resolved
Comment thread src/stages/buildReplacementHandlers.ts Resolved
@benney
benney requested a review from JFL110 November 5, 2026 17:27
@benney
benney merged commit 6d1d24f into main Nov 6, 2026
3 checks passed
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.

3 participants