Skip to content

Commit

Permalink
[Fix] no-invalid-html-attribute: ensure error messages are correct
Browse files Browse the repository at this point in the history
  • Loading branch information
mdjermanovic authored and ljharb committed May 20, 2024
1 parent 23b0a49 commit 014ee05
Show file tree
Hide file tree
Showing 3 changed files with 193 additions and 45 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
* [`boolean-prop-naming`]: avoid a crash with a non-TSTypeReference type ([#3718][] @developer-bandi)
* [`jsx-no-leaked-render`]: invalid report if left side is boolean ([#3746][] @akulsr0)
* [`jsx-closing-bracket-location`]: message shows `{{details}}` when there are no details ([#3759][] @mdjermanovic)
* [`no-invalid-html-attribute`]: ensure error messages are correct ([#3759][] @mdjermanovic, @ljharb)

[#3759]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3759
[#3746]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3746
Expand Down
120 changes: 82 additions & 38 deletions lib/rules/no-invalid-html-attribute.js
Original file line number Diff line number Diff line change
Expand Up @@ -238,8 +238,8 @@ const messages = {
suggestRemoveDefault: '"remove {{attributeName}}"',
suggestRemoveEmpty: '"remove empty attribute {{attributeName}}"',
suggestRemoveInvalid: '“remove invalid attribute {{reportingValue}}”',
suggestRemoveWhitespaces: 'remove whitespaces in “{{reportingValue}}”',
suggestRemoveNonString: 'remove non-string value in “{{reportingValue}}”',
suggestRemoveWhitespaces: 'remove whitespaces in “{{attributeName}}”',
suggestRemoveNonString: 'remove non-string value in “{{attributeName}}”',
};

function splitIntoRangedParts(node, regex) {
Expand All @@ -259,27 +259,37 @@ function splitIntoRangedParts(node, regex) {

function checkLiteralValueNode(context, attributeName, node, parentNode, parentNodeName) {
if (typeof node.value !== 'string') {
const data = { attributeName, reportingValue: node.value };

report(context, messages.onlyStrings, 'onlyStrings', {
node,
data: { attributeName },
data,
suggest: [
Object.assign(
getMessageData('suggestRemoveNonString', messages.suggestRemoveNonString),
{ fix(fixer) { return fixer.remove(parentNode); } }
{
data,
fix(fixer) { return fixer.remove(parentNode); },
}
),
],
});
return;
}

if (!node.value.trim()) {
const data = { attributeName, reportingValue: node.value };

report(context, messages.noEmpty, 'noEmpty', {
node,
data: { attributeName },
data,
suggest: [
Object.assign(
getMessageData('suggestRemoveEmpty', messages.suggestRemoveEmpty),
{ fix(fixer) { return fixer.remove(node.parent); } }
{
data,
fix(fixer) { return fixer.remove(node.parent); },
}
),
],
});
Expand All @@ -291,32 +301,44 @@ function checkLiteralValueNode(context, attributeName, node, parentNode, parentN
const allowedTags = VALID_VALUES.get(attributeName).get(singlePart.value);
const reportingValue = singlePart.reportingValue;

const suggest = [
Object.assign(
getMessageData('suggestRemoveInvalid', messages.suggestRemoveInvalid),
{ fix(fixer) { return fixer.removeRange(singlePart.range); } }
),
];

if (!allowedTags) {
const data = {
attributeName,
reportingValue,
};

report(context, messages.neverValid, 'neverValid', {
node,
data,
suggest,
suggest: [
Object.assign(
getMessageData('suggestRemoveInvalid', messages.suggestRemoveInvalid),
{
data,
fix(fixer) { return fixer.removeRange(singlePart.range); },
}
),
],
});
} else if (!allowedTags.has(parentNodeName)) {
const data = {
attributeName,
reportingValue,
elementName: parentNodeName,
};

report(context, messages.notValidFor, 'notValidFor', {
node,
data: {
attributeName,
reportingValue,
elementName: parentNodeName,
},
suggest,
data,
suggest: [
Object.assign(
getMessageData('suggestRemoveInvalid', messages.suggestRemoveInvalid),
{
data,
fix(fixer) { return fixer.removeRange(singlePart.range); },
}
),
],
});
}
}
Expand Down Expand Up @@ -360,7 +382,10 @@ function checkLiteralValueNode(context, attributeName, node, parentNode, parentN
suggest: [
Object.assign(
getMessageData('suggestRemoveWhitespaces', messages.suggestRemoveWhitespaces),
{ fix(fixer) { return fixer.removeRange(whitespacePart.range); } }
{
data: { attributeName },
fix(fixer) { return fixer.removeRange(whitespacePart.range); },
}
),
],
});
Expand All @@ -371,7 +396,10 @@ function checkLiteralValueNode(context, attributeName, node, parentNode, parentN
suggest: [
Object.assign(
getMessageData('suggestRemoveWhitespaces', messages.suggestRemoveWhitespaces),
{ fix(fixer) { return fixer.replaceTextRange(whitespacePart.range, '\u0020'); } }
{
data: { attributeName },
fix(fixer) { return fixer.replaceTextRange(whitespacePart.range, '\u0020'); },
}
),
],
});
Expand All @@ -390,16 +418,21 @@ function checkAttribute(context, node) {
COMPONENT_ATTRIBUTE_MAP.get(attribute).values(),
(tagName) => `"<${tagName}>"`
).join(', ');
const data = {
attributeName: attribute,
tagNames,
};

report(context, messages.onlyMeaningfulFor, 'onlyMeaningfulFor', {
node: node.name,
data: {
attributeName: attribute,
tagNames,
},
data,
suggest: [
Object.assign(
getMessageData('suggestRemoveDefault', messages.suggestRemoveDefault),
{ fix(fixer) { return fixer.remove(node); } }
{
data,
fix(fixer) { return fixer.remove(node); },
}
),
],
});
Expand All @@ -409,13 +442,15 @@ function checkAttribute(context, node) {
function fix(fixer) { return fixer.remove(node); }

if (!node.value) {
const data = { attributeName: attribute };

report(context, messages.emptyIsMeaningless, 'emptyIsMeaningless', {
node: node.name,
data: { attributeName: attribute },
data,
suggest: [
Object.assign(
getMessageData('suggestRemoveEmpty', messages.suggestRemoveEmpty),
{ fix }
{ data, fix }
),
],
});
Expand All @@ -435,24 +470,28 @@ function checkAttribute(context, node) {
}

if (node.value.expression.type === 'ObjectExpression') {
const data = { attributeName: attribute };

report(context, messages.onlyStrings, 'onlyStrings', {
node: node.value,
data: { attributeName: attribute },
data,
suggest: [
Object.assign(
getMessageData('suggestRemoveDefault', messages.suggestRemoveDefault),
{ fix }
{ data, fix }
),
],
});
} else if (node.value.expression.type === 'Identifier' && node.value.expression.name === 'undefined') {
const data = { attributeName: attribute };

report(context, messages.onlyStrings, 'onlyStrings', {
node: node.value,
data: { attributeName: attribute },
data,
suggest: [
Object.assign(
getMessageData('suggestRemoveDefault', messages.suggestRemoveDefault),
{ fix }
{ data, fix }
),
],
});
Expand All @@ -476,16 +515,21 @@ function checkPropValidValue(context, node, value, attribute) {

const validTagSet = validTags.get(value.value);
if (!validTagSet) {
const data = {
attributeName: attribute,
reportingValue: value.value,
};

report(context, messages.neverValid, 'neverValid', {
node: value,
data: {
attributeName: attribute,
reportingValue: value.value,
},
data,
suggest: [
Object.assign(
getMessageData('suggestRemoveInvalid', messages.suggestRemoveInvalid),
{ fix(fixer) { return fixer.replaceText(value, value.raw.replace(value.value, '')); } }
{
data,
fix(fixer) { return fixer.replaceText(value, value.raw.replace(value.value, '')); },
}
),
],
});
Expand Down
Loading

0 comments on commit 014ee05

Please sign in to comment.