Skip to content

Commit bd7a4df

Browse files
authored
Refactor prefer-dataset with selector (#515)
1 parent 8f81fee commit bd7a4df

File tree

2 files changed

+46
-51
lines changed

2 files changed

+46
-51
lines changed

β€Žrules/prefer-dataset.jsβ€Ž

Lines changed: 25 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,48 @@
11
'use strict';
22
const getDocumentationUrl = require('./utils/get-documentation-url');
33
const isValidVariableName = require('./utils/is-valid-variable-name');
4+
const quoteString = require('./utils/quote-string');
5+
const methodSelector = require('./utils/method-selector');
46

5-
const getMethodName = memberExpression => memberExpression.property.name;
6-
7-
const getDataAttributeName = argument => {
8-
if (argument.type === 'Literal') {
9-
const matches = /^data-(?<name>.+)/.exec(argument.value);
10-
return matches ? matches.groups.name : '';
11-
}
12-
13-
return '';
14-
};
7+
const selector = methodSelector({
8+
name: 'setAttribute',
9+
length: 2
10+
}) + '[arguments.0.type="Literal"]';
1511

1612
const parseNodeText = (context, argument) => context.getSourceCode().getText(argument);
1713

1814
const dashToCamelCase = string => string.replace(/-[a-z]/g, s => s[1].toUpperCase());
1915

20-
const getReplacement = (context, node, memberExpression, propertyName) => {
21-
const calleeObject = parseNodeText(context, memberExpression.object);
22-
const value = parseNodeText(context, node.arguments[1]);
16+
const fix = (context, node, fixer) => {
17+
let [name, value] = node.arguments;
18+
const calleeObject = parseNodeText(context, node.callee.object);
2319

24-
propertyName = dashToCamelCase(propertyName);
25-
26-
if (!isValidVariableName(propertyName)) {
27-
return `${calleeObject}.dataset['${propertyName}'] = ${value}`;
28-
}
29-
30-
return `${calleeObject}.dataset.${propertyName} = ${value}`;
31-
};
20+
name = dashToCamelCase(name.value.slice(5));
21+
value = parseNodeText(context, value);
3222

33-
const isBracketNotation = (context, callee) => {
34-
const bracketOpen = context
35-
.getSourceCode()
36-
.getFirstTokenBetween(callee.object, callee.property, {
37-
filter: token => token.value === '['
38-
});
23+
const replacement = `${calleeObject}.dataset${
24+
isValidVariableName(name) ?
25+
`.${name}` :
26+
`[${quoteString(name)}]`
27+
} = ${value}`;
3928

40-
return bracketOpen !== null && bracketOpen.value === '[';
29+
return fixer.replaceText(node, replacement);
4130
};
4231

4332
const create = context => {
4433
return {
45-
CallExpression(node) {
46-
const {callee} = node;
34+
[selector](node) {
35+
const name = node.arguments[0].value;
4736

48-
if (callee.type !== 'MemberExpression') {
37+
if (typeof name !== 'string' || !name.startsWith('data-') || name === 'data-') {
4938
return;
5039
}
5140

52-
if (getMethodName(callee) !== 'setAttribute') {
53-
return;
54-
}
55-
56-
if (isBracketNotation(context, callee)) {
57-
return;
58-
}
59-
60-
const attributeName = getDataAttributeName(node.arguments[0]);
61-
if (attributeName) {
62-
const replacement = getReplacement(context, node, callee, attributeName);
63-
context.report({
64-
node,
65-
message: 'Prefer `.dataset` over `setAttribute(…)`.',
66-
fix: fixer => fixer.replaceText(node, replacement)
67-
});
68-
}
41+
context.report({
42+
node,
43+
message: 'Prefer `.dataset` over `setAttribute(…)`.',
44+
fix: fixer => fix(context, node, fixer)
45+
});
6946
}
7047
};
7148
};

β€Žtest/prefer-dataset.jsβ€Ž

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,28 @@ ruleTester.run('prefer-dataset', rule, {
2020
valid: [
2121
'element.dataset.unicorn = \'πŸ¦„\';',
2222
'element.dataset[\'unicorn\'] = \'πŸ¦„\';',
23+
// Not `CallExpression`
24+
'new element.setAttribute(\'data-unicorn\', \'πŸ¦„\');',
25+
// Not `MemberExpression`
26+
'setAttribute(\'data-unicorn\', \'πŸ¦„\');',
27+
// `callee.property` is not a `Identifier`
28+
'element[\'setAttribute\'](\'data-unicorn\', \'πŸ¦„\');',
29+
// Computed
2330
'element[setAttribute](\'data-unicorn\', \'πŸ¦„\');',
24-
'element.setAttribute(\'foo\', \'bar\');',
25-
'element.setAttribute(foo, bar);',
26-
'element.getAttribute(\'data-unicorn\');'
31+
// Not `appendChild`
32+
'element.foo(\'data-unicorn\', \'πŸ¦„\');',
33+
// More or less argument(s)
34+
'element.setAttribute(\'data-unicorn\', \'πŸ¦„\', \'extra\');',
35+
'element.setAttribute(\'data-unicorn\');',
36+
'element.setAttribute(...argumentsArray, ...argumentsArray2)',
37+
// First Argument is not `Literal`
38+
'element.setAttribute(`data-unicorn`, \'πŸ¦„\');',
39+
// First Argument is not `string`
40+
'element.setAttribute(0, \'πŸ¦„\');',
41+
// First Argument is not startsWith `data-`
42+
'element.setAttribute(\'foo-unicorn\', \'πŸ¦„\');',
43+
// First Argument is `data-`
44+
'element.setAttribute(\'data-\', \'πŸ¦„\');'
2745
],
2846
invalid: [
2947
{

0 commit comments

Comments
Β (0)