Skip to content

Commit fd5f0bf

Browse files
authored
fix: attribute case insensitivity parsing
1 parent c3db2ff commit fd5f0bf

File tree

3 files changed

+56
-3
lines changed

3 files changed

+56
-3
lines changed

src/__tests__/attributes.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,10 +352,38 @@ test('insensitive attribute selector 2', '[href=TEsT i ]', (t, tree) => {
352352
test('insensitive attribute selector 3', '[href=test i]', (t, tree) => {
353353
t.deepEqual(tree.nodes[0].nodes[0].value, 'test');
354354
t.deepEqual(tree.nodes[0].nodes[0].insensitive, true);
355+
356+
tree.nodes[0].nodes[0].insensitive = false;
357+
358+
t.deepEqual(tree.toString(), '[href=test ]');
355359
});
356360
test('capitalized insensitive attribute selector 3', '[href=test I]', (t, tree) => {
357361
t.deepEqual(tree.nodes[0].nodes[0].value, 'test');
358362
t.deepEqual(tree.nodes[0].nodes[0].insensitive, true);
363+
364+
tree.nodes[0].nodes[0].insensitive = false;
365+
366+
t.deepEqual(tree.toString(), '[href=test ]');
367+
});
368+
369+
test('insensitive attribute selector 4', '[href="test"i]', (t, tree) => {
370+
t.deepEqual(tree.nodes[0].nodes[0].value, 'test');
371+
t.deepEqual(tree.nodes[0].nodes[0].insensitive, true);
372+
});
373+
374+
test('capitalized insensitive attribute selector 4', '[href="test"I]', (t, tree) => {
375+
t.deepEqual(tree.nodes[0].nodes[0].value, 'test');
376+
t.deepEqual(tree.nodes[0].nodes[0].insensitive, true);
377+
});
378+
379+
test('insensitive attribute selector 5', '[href="test" i ]', (t, tree) => {
380+
t.deepEqual(tree.nodes[0].nodes[0].value, 'test');
381+
t.deepEqual(tree.nodes[0].nodes[0].insensitive, true);
382+
});
383+
384+
test('insensitive attribute selector 6', '[href=test i ]', (t, tree) => {
385+
t.deepEqual(tree.nodes[0].nodes[0].value, 'test');
386+
t.deepEqual(tree.nodes[0].nodes[0].insensitive, true);
359387
});
360388

361389
test('extraneous non-combinating whitespace', ' [href] , [class] ', (t, tree) => {

src/parser.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ export default class Parser {
301301
node.raws.attribute += content;
302302
}
303303
lastAdded = 'attribute';
304-
} else if ((!node.value && node.value !== "") || (lastAdded === "value" && !spaceAfterMeaningfulToken)) {
304+
} else if ((!node.value && node.value !== "") || (lastAdded === "value" && !(spaceAfterMeaningfulToken || node.quoteMark))) {
305305
let unescaped = unesc(content);
306306
let oldRawValue = getProp(node, 'raws', 'value') || '';
307307
let oldValue = node.value || '';
@@ -464,8 +464,8 @@ export default class Parser {
464464
}
465465

466466
/**
467-
*
468-
* @param {*} nodes
467+
*
468+
* @param {*} nodes
469469
*/
470470
convertWhitespaceNodesToSpace (nodes, requiredSpace = false) {
471471
let space = "";

src/selectors/attribute.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,31 @@ export default class Attribute extends Namespace {
238238
return this._value;
239239
}
240240

241+
get insensitive () {
242+
return this._insensitive;
243+
}
244+
245+
/**
246+
* Set the case insensitive flag.
247+
* If the case insensitive flag changes, the raw (escaped) value at `attr.raws.insensitiveFlag`
248+
* of the attribute is updated accordingly.
249+
*
250+
* @param {true | false} insensitive true if the attribute should match case-insensitively.
251+
*/
252+
set insensitive (insensitive) {
253+
if (!insensitive) {
254+
this._insensitive = false;
255+
256+
// "i" and "I" can be used in "this.raws.insensitiveFlag" to store the original notation.
257+
// When setting `attr.insensitive = false` both should be erased to ensure correct serialization.
258+
if (this.raws && (this.raws.insensitiveFlag === 'I' || this.raws.insensitiveFlag === 'i')) {
259+
this.raws.insensitiveFlag = undefined;
260+
}
261+
}
262+
263+
this._insensitive = insensitive;
264+
}
265+
241266
/**
242267
* Before 3.0, the value had to be set to an escaped value including any wrapped
243268
* quote marks. In 3.0, the semantics of `Attribute.value` changed so that the value

0 commit comments

Comments
 (0)