fix: support textContent swap style for hx-swap-oob (#3563)#3768
Open
manwithacat wants to merge 1 commit intobigskysoftware:devfrom
Open
fix: support textContent swap style for hx-swap-oob (#3563)#3768manwithacat wants to merge 1 commit intobigskysoftware:devfrom
manwithacat wants to merge 1 commit intobigskysoftware:devfrom
Conversation
) swapWithStyle() handled none, outerHTML, afterbegin, beforebegin, beforeend, afterend, and delete, but had no case for textContent. Falling through to the default branch caused textContent OOB swaps to be treated as innerHTML, parsing the response body as HTML instead of inserting it as literal text. Mirrors the main-swap textContent handling, which sets target.textContent directly without parsing as HTML. Fixes bigskysoftware#3563 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #3563.
The bug
swapWithStyle()(src/htmx.js:1799) has cases for every OOB swap style —none,outerHTML,afterbegin,beforebegin,beforeend,afterend,delete— but no case fortextContent. Falling into thedefaultbranch eventually recurses withhtmx.config.defaultSwapStyle(normallyinnerHTML), so anhx-swap-oob="textContent"swap silently behaves like aninnerHTMLswap.This contradicts the documented
textContentcontract — hx-swap docs say:The primary-swap path already handles this correctly at
src/htmx.js:1907(target.textContent = content, before any HTML parsing). The OOB path was the outlier.The fix
Add a
case 'textContent'toswapWithStylemirroring the primary-swap behavior:For non-inline OOB swaps,
oobSwap()setsfragmentto the parsed OOB element clone (line 1492), sofragment.textContentis the concatenated text of all descendants — matching the OOB doc rule that "the encapsulating tag pair will be stripped for all strategies other thanouterHTML".3 lines in
src/htmx.js.Tests
Two new cases in
test/attributes/hx-swap-oob.js:handles textContent response properly— verifies<h1>Swapped</h1>inside an OOB element becomes literal textSwappedin the target, not a parsed<h1>element.handles textContent oob swap with selector— verifies thetextContent:#selectorform works the same way.Both fail before the fix (the
<h1>is parsed and inserted as an element), pass after.Full suite: 848 passed, 0 failed, 3 skipped, 99.9% coverage. ESLint clean.
Live before/after demo
https://manwithacat.github.io/htmx/demos/hx-swap-oob-textContent/
Side-by-side iframes load the same base commit (
d53932d4) with and without this 3-line patch, using a mockXMLHttpRequestso htmx runs its real lifecycle without needing a server. The buggy panel renders the OOB response's<h1>as a real DOM element; the fixed panel renders it as literal text.Notes for reviewers
cleanUpElement()calls for removed children before assigningtarget.textContent. The primary-swap textContent path atsrc/htmx.js:1908doesn't either, and adding cleanup only on the OOB side would be inconsistent. Happy to follow up with a separate PR that adds it to both paths if that's wanted.hx-swap.mdalready liststextContentandhx-swap-oob.mdalready says any validhx-swapvalue works. The docs were correct; the code was the outlier.