Skip to content

Commit d53932d

Browse files
improve escaping of tag and id in settle lookup (#3752)
Thank you!
1 parent 6ff7c48 commit d53932d

2 files changed

Lines changed: 30 additions & 6 deletions

File tree

src/htmx.js

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1560,10 +1560,8 @@ var htmx = (function() {
15601560
forEach(fragment.querySelectorAll('[id]'), function(newNode) {
15611561
const id = getRawAttribute(newNode, 'id')
15621562
if (id && id.length > 0) {
1563-
const normalizedId = id.replace("'", "\\'")
1564-
const normalizedTag = newNode.tagName.replace(':', '\\:')
15651563
const parentElt = asParentNode(parentNode)
1566-
const oldNode = parentElt && parentElt.querySelector(normalizedTag + "[id='" + normalizedId + "']")
1564+
const oldNode = parentElt && parentElt.querySelector(CSS.escape(newNode.tagName) + '#' + CSS.escape(id))
15671565
if (oldNode && oldNode !== parentElt) {
15681566
const newAttributes = newNode.cloneNode()
15691567
cloneAttributes(newNode, oldNode)
@@ -1979,7 +1977,7 @@ var htmx = (function() {
19791977
removeClassFromElement(target, htmx.config.swappingClass)
19801978
forEach(settleInfo.elts, function(elt) {
19811979
if (elt.classList) {
1982-
elt.classList.add(htmx.config.settlingClass)
1980+
addClassToElement(elt, htmx.config.settlingClass)
19831981
}
19841982
triggerEvent(elt, 'htmx:afterSwap', swapOptions.eventInfo)
19851983
})
@@ -3378,7 +3376,7 @@ var htmx = (function() {
33783376
forEach(indicators, function(ic) {
33793377
const internalData = getInternalData(ic)
33803378
internalData.requestCount = (internalData.requestCount || 0) + 1
3381-
ic.classList.add.call(ic.classList, htmx.config.requestClass)
3379+
addClassToElement(ic, htmx.config.requestClass)
33823380
})
33833381
return indicators
33843382
}
@@ -4915,7 +4913,7 @@ var htmx = (function() {
49154913
swapSpec.ignoreTitle = ignoreTitle
49164914
}
49174915

4918-
target.classList.add(htmx.config.swappingClass)
4916+
addClassToElement(target, htmx.config.swappingClass)
49194917

49204918
if (responseInfoSelect) {
49214919
selectOverride = responseInfoSelect

test/core/ajax.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,18 @@ describe('Core htmx AJAX Tests', function() {
341341
}, 20)
342342
})
343343

344+
it('properly settles attributes elements with multiple single quotes in id', function(done) {
345+
this.server.respondWith('GET', '/test', "<div hx-get='/test'><div width='bar' id=\"fo'o'bar\"></div></div>")
346+
var div = make("<div hx-get='/test' hx-swap='outerHTML settle:10ms'><div id=\"fo'o'bar\"></div></div>")
347+
div.click()
348+
this.server.respond()
349+
should.equal(byId("fo'o'bar").getAttribute('width'), null)
350+
setTimeout(function() {
351+
should.equal(byId("fo'o'bar").getAttribute('width'), 'bar')
352+
done()
353+
}, 20)
354+
})
355+
344356
it('properly settles attributes elements with double quotes in id', function(done) {
345357
this.server.respondWith('GET', '/test', "<div hx-get='/test'><div width='bar' id='d1\"'></div></div>")
346358
var div = make("<div hx-get='/test' hx-swap='outerHTML settle:10ms'><div id='d1\"'></div></div>")
@@ -992,6 +1004,20 @@ describe('Core htmx AJAX Tests', function() {
9921004
btn.innerHTML.should.equal('<with:colon id="foobar">Foobar</with:colon>')
9931005
})
9941006

1007+
it('falls back to DOMParser when parseHTMLUnsafe is not available', function() {
1008+
const original = Document.parseHTMLUnsafe
1009+
try {
1010+
delete Document.parseHTMLUnsafe
1011+
this.server.respondWith('GET', '/test', '<div id="d1">Fallback</div>')
1012+
var div = make('<div hx-get="/test" hx-select="#d1"></div>')
1013+
div.click()
1014+
this.server.respond()
1015+
div.innerHTML.should.equal('<div id="d1">Fallback</div>')
1016+
} finally {
1017+
Document.parseHTMLUnsafe = original
1018+
}
1019+
})
1020+
9951021
it('properly handles clicked submit button with a value inside a htmx form', function() {
9961022
var values
9971023
this.server.respondWith('Post', '/test', function(xhr) {

0 commit comments

Comments
 (0)