|
1 | 1 | 'use strict'; |
2 | 2 | const getDocumentationUrl = require('./utils/get-documentation-url'); |
3 | 3 | const isValidVariableName = require('./utils/is-valid-variable-name'); |
| 4 | +const quoteString = require('./utils/quote-string'); |
| 5 | +const methodSelector = require('./utils/method-selector'); |
4 | 6 |
|
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"]'; |
15 | 11 |
|
16 | 12 | const parseNodeText = (context, argument) => context.getSourceCode().getText(argument); |
17 | 13 |
|
18 | 14 | const dashToCamelCase = string => string.replace(/-[a-z]/g, s => s[1].toUpperCase()); |
19 | 15 |
|
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); |
23 | 19 |
|
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); |
32 | 22 |
|
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}`; |
39 | 28 |
|
40 | | - return bracketOpen !== null && bracketOpen.value === '['; |
| 29 | + return fixer.replaceText(node, replacement); |
41 | 30 | }; |
42 | 31 |
|
43 | 32 | const create = context => { |
44 | 33 | return { |
45 | | - CallExpression(node) { |
46 | | - const {callee} = node; |
| 34 | + [selector](node) { |
| 35 | + const name = node.arguments[0].value; |
47 | 36 |
|
48 | | - if (callee.type !== 'MemberExpression') { |
| 37 | + if (typeof name !== 'string' || !name.startsWith('data-') || name === 'data-') { |
49 | 38 | return; |
50 | 39 | } |
51 | 40 |
|
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 | + }); |
69 | 46 | } |
70 | 47 | }; |
71 | 48 | }; |
|
0 commit comments