Skip to content

Commit

Permalink
Fix selector-attribute-quotes end positions (#6226)
Browse files Browse the repository at this point in the history
  • Loading branch information
ybiquitous committed Jul 28, 2022
1 parent c7caca3 commit f02ee48
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 18 deletions.
46 changes: 46 additions & 0 deletions lib/rules/selector-attribute-quotes/__tests__/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,62 +71,80 @@ testRule({
message: messages.expected('flower'),
line: 1,
column: 9,
endLine: 1,
endColumn: 15,
},
{
code: 'a[ title=flower ] { }',
fixed: 'a[ title="flower" ] { }',
message: messages.expected('flower'),
line: 1,
column: 10,
endLine: 1,
endColumn: 16,
},
{
code: '[class^=top] { }',
fixed: '[class^="top"] { }',
message: messages.expected('top'),
line: 1,
column: 9,
endLine: 1,
endColumn: 12,
},
{
code: '[class ^= top] { }',
fixed: '[class ^= "top"] { }',
message: messages.expected('top'),
line: 1,
column: 11,
endLine: 1,
endColumn: 14,
},
{
code: '[frame=hsides i] { }',
fixed: '[frame="hsides" i] { }',
message: messages.expected('hsides'),
line: 1,
column: 8,
endLine: 1,
endColumn: 14,
},
{
code: '[data-style=value][data-loading] { }',
fixed: '[data-style="value"][data-loading] { }',
message: messages.expected('value'),
line: 1,
column: 13,
endLine: 1,
endColumn: 18,
},
{
code: `[href=te\\'s\\"t] { }`,
fixed: `[href="te's\\"t"] { }`,
message: messages.expected(`te's"t`),
line: 1,
column: 7,
endLine: 1,
endColumn: 15,
},
{
code: '[href=\\"test\\"] { }',
fixed: '[href="\\"test\\""] { }',
message: messages.expected('"test"'),
line: 1,
column: 7,
endLine: 1,
endColumn: 15,
},
{
code: "[href=\\'test\\'] { }",
fixed: `[href="'test'"] { }`,
message: messages.expected("'test'"),
line: 1,
column: 7,
endLine: 1,
endColumn: 15,
},
],
});
Expand Down Expand Up @@ -173,97 +191,125 @@ testRule({
message: messages.rejected('_blank'),
line: 1,
column: 10,
endLine: 1,
endColumn: 18,
},
{
code: 'a[ target="_blank" ] { }',
fixed: 'a[ target=_blank ] { }',
message: messages.rejected('_blank'),
line: 1,
column: 11,
endLine: 1,
endColumn: 19,
},
{
code: '[class|="top"] { }',
fixed: '[class|=top] { }',
message: messages.rejected('top'),
line: 1,
column: 9,
endLine: 1,
endColumn: 14,
},
{
code: '[class |= "top"] { }',
fixed: '[class |= top] { }',
message: messages.rejected('top'),
line: 1,
column: 11,
endLine: 1,
endColumn: 16,
},
{
code: "[title~='text'] { }",
fixed: '[title~=text] { }',
message: messages.rejected('text'),
line: 1,
column: 9,
endLine: 1,
endColumn: 15,
},
{
code: "[data-attribute='component'] { }",
fixed: '[data-attribute=component] { }',
message: messages.rejected('component'),
line: 1,
column: 17,
endLine: 1,
endColumn: 28,
},
{
code: '[frame="hsides" i] { }',
fixed: '[frame=hsides i] { }',
message: messages.rejected('hsides'),
line: 1,
column: 8,
endLine: 1,
endColumn: 16,
},
{
code: "[frame='hsides' i] { }",
fixed: '[frame=hsides i] { }',
message: messages.rejected('hsides'),
line: 1,
column: 8,
endLine: 1,
endColumn: 16,
},
{
code: "[data-style='value'][data-loading] { }",
fixed: '[data-style=value][data-loading] { }',
message: messages.rejected('value'),
line: 1,
column: 13,
endLine: 1,
endColumn: 20,
},
{
code: `[href="te'st"] { }`,
fixed: "[href=te\\'st] { }",
message: messages.rejected("te'st"),
line: 1,
column: 7,
endLine: 1,
endColumn: 14,
},
{
code: `[href='te"st'] { }`,
fixed: '[href=te\\"st] { }',
message: messages.rejected('te"st'),
line: 1,
column: 7,
endLine: 1,
endColumn: 14,
},
{
code: "[href='te\\'s\\'t'] { }",
fixed: "[href=te\\'s\\'t] { }",
message: messages.rejected("te's't"),
line: 1,
column: 7,
endLine: 1,
endColumn: 17,
},
{
code: '[href="te\\"s\\"t"] { }',
fixed: '[href=te\\"s\\"t] { }',
message: messages.rejected('te"s"t'),
line: 1,
column: 7,
endLine: 1,
endColumn: 17,
},
{
code: 'a[target="_blank"], /* comment */ a { }',
fixed: 'a[target=_blank], /* comment */ a { }',
message: messages.rejected('_blank'),
line: 1,
column: 10,
endLine: 1,
endColumn: 18,
},
],
});
Expand Down
36 changes: 18 additions & 18 deletions lib/rules/selector-attribute-quotes/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ const parseSelector = require('../../utils/parseSelector');
const report = require('../../utils/report');
const ruleMessages = require('../../utils/ruleMessages');
const validateOptions = require('../../utils/validateOptions');
const { assertString } = require('../../utils/validateTypes');

const ruleName = 'selector-attribute-quotes';

Expand All @@ -22,7 +21,7 @@ const meta = {

const acceptedQuoteMark = '"';

/** @type {import('stylelint').Rule} */
/** @type {import('stylelint').Rule<'always' | 'never'>} */
const rule = (primary, _secondaryOptions, context) => {
return (root, result) => {
const validOptions = validateOptions(result, ruleName, {
Expand All @@ -39,41 +38,37 @@ const rule = (primary, _secondaryOptions, context) => {
return;
}

if (!ruleNode.selector.includes('[') || !ruleNode.selector.includes('=')) {
const { selector } = ruleNode;

if (!selector.includes('[') || !selector.includes('=')) {
return;
}

parseSelector(getRuleSelector(ruleNode), result, ruleNode, (selectorTree) => {
let selectorFixed = false;

selectorTree.walkAttributes((attributeNode) => {
if (!attributeNode.operator) {
const { operator, value, quoted } = attributeNode;

if (!operator || !value) {
return;
}

if (!attributeNode.quoted && primary === 'always') {
if (!quoted && primary === 'always') {
if (context.fix) {
selectorFixed = true;
attributeNode.quoteMark = acceptedQuoteMark;
} else {
assertString(attributeNode.value);
complain(
messages.expected(attributeNode.value),
attributeNode.sourceIndex + attributeNode.offsetOf('value'),
);
complain(messages.expected(value), attributeNode);
}
}

if (attributeNode.quoted && primary === 'never') {
if (quoted && primary === 'never') {
if (context.fix) {
selectorFixed = true;
attributeNode.quoteMark = null;
} else {
assertString(attributeNode.value);
complain(
messages.rejected(attributeNode.value),
attributeNode.sourceIndex + attributeNode.offsetOf('value'),
);
complain(messages.rejected(value), attributeNode);
}
}
});
Expand All @@ -85,12 +80,17 @@ const rule = (primary, _secondaryOptions, context) => {

/**
* @param {string} message
* @param {number} index
* @param {import('postcss-selector-parser').Attribute} attrNode
*/
function complain(message, index) {
function complain(message, attrNode) {
const index = attrNode.sourceIndex + attrNode.offsetOf('value');
const value = attrNode.raws.value || attrNode.value || '';
const endIndex = index + value.length;

report({
message,
index,
endIndex,
result,
ruleName,
node: ruleNode,
Expand Down

0 comments on commit f02ee48

Please sign in to comment.