@atlaskit/eslint-plugin-design-system 13.12.0 → 13.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/README.md +2 -0
- package/dist/cjs/presets/all-flat.codegen.js +3 -1
- package/dist/cjs/presets/all.codegen.js +3 -1
- package/dist/cjs/presets/recommended-flat.codegen.js +3 -1
- package/dist/cjs/presets/recommended.codegen.js +3 -1
- package/dist/cjs/rules/index.codegen.js +5 -1
- package/dist/cjs/rules/no-html-text-input/index.js +34 -0
- package/dist/cjs/rules/no-html-text-input/node-types/index.js +12 -0
- package/dist/cjs/rules/no-html-text-input/node-types/jsx-element/index.js +115 -0
- package/dist/cjs/rules/no-html-text-input/node-types/supported.js +91 -0
- package/dist/cjs/rules/no-html-textarea/index.js +40 -0
- package/dist/cjs/rules/no-html-textarea/node-types/index.js +19 -0
- package/dist/cjs/rules/no-html-textarea/node-types/jsx-element/index.js +112 -0
- package/dist/cjs/rules/no-html-textarea/node-types/styled-component/index.js +42 -0
- package/dist/cjs/rules/no-html-textarea/node-types/supported.js +66 -0
- package/dist/es2019/presets/all-flat.codegen.js +3 -1
- package/dist/es2019/presets/all.codegen.js +3 -1
- package/dist/es2019/presets/recommended-flat.codegen.js +3 -1
- package/dist/es2019/presets/recommended.codegen.js +3 -1
- package/dist/es2019/rules/index.codegen.js +5 -1
- package/dist/es2019/rules/no-html-text-input/index.js +28 -0
- package/dist/es2019/rules/no-html-text-input/node-types/index.js +1 -0
- package/dist/es2019/rules/no-html-text-input/node-types/jsx-element/index.js +80 -0
- package/dist/es2019/rules/no-html-text-input/node-types/supported.js +79 -0
- package/dist/es2019/rules/no-html-textarea/index.js +34 -0
- package/dist/es2019/rules/no-html-textarea/node-types/index.js +2 -0
- package/dist/es2019/rules/no-html-textarea/node-types/jsx-element/index.js +79 -0
- package/dist/es2019/rules/no-html-textarea/node-types/styled-component/index.js +37 -0
- package/dist/es2019/rules/no-html-textarea/node-types/supported.js +56 -0
- package/dist/esm/presets/all-flat.codegen.js +3 -1
- package/dist/esm/presets/all.codegen.js +3 -1
- package/dist/esm/presets/recommended-flat.codegen.js +3 -1
- package/dist/esm/presets/recommended.codegen.js +3 -1
- package/dist/esm/rules/index.codegen.js +5 -1
- package/dist/esm/rules/no-html-text-input/index.js +28 -0
- package/dist/esm/rules/no-html-text-input/node-types/index.js +1 -0
- package/dist/esm/rules/no-html-text-input/node-types/jsx-element/index.js +106 -0
- package/dist/esm/rules/no-html-text-input/node-types/supported.js +82 -0
- package/dist/esm/rules/no-html-textarea/index.js +34 -0
- package/dist/esm/rules/no-html-textarea/node-types/index.js +2 -0
- package/dist/esm/rules/no-html-textarea/node-types/jsx-element/index.js +103 -0
- package/dist/esm/rules/no-html-textarea/node-types/styled-component/index.js +36 -0
- package/dist/esm/rules/no-html-textarea/node-types/supported.js +57 -0
- package/dist/types/index.codegen.d.ts +18 -0
- package/dist/types/presets/all-flat.codegen.d.ts +2 -0
- package/dist/types/presets/all.codegen.d.ts +2 -0
- package/dist/types/presets/recommended-flat.codegen.d.ts +2 -0
- package/dist/types/presets/recommended.codegen.d.ts +2 -0
- package/dist/types/rules/index.codegen.d.ts +2 -0
- package/dist/types/rules/no-html-text-input/index.d.ts +3 -0
- package/dist/types/rules/no-html-text-input/node-types/index.d.ts +1 -0
- package/dist/types/rules/no-html-text-input/node-types/jsx-element/index.d.ts +8 -0
- package/dist/types/rules/no-html-text-input/node-types/supported.d.ts +7 -0
- package/dist/types/rules/no-html-textarea/index.d.ts +3 -0
- package/dist/types/rules/no-html-textarea/node-types/index.d.ts +2 -0
- package/dist/types/rules/no-html-textarea/node-types/jsx-element/index.d.ts +8 -0
- package/dist/types/rules/no-html-textarea/node-types/styled-component/index.d.ts +8 -0
- package/dist/types/rules/no-html-textarea/node-types/supported.d.ts +7 -0
- package/dist/types-ts4.5/index.codegen.d.ts +18 -0
- package/dist/types-ts4.5/presets/all-flat.codegen.d.ts +2 -0
- package/dist/types-ts4.5/presets/all.codegen.d.ts +2 -0
- package/dist/types-ts4.5/presets/recommended-flat.codegen.d.ts +2 -0
- package/dist/types-ts4.5/presets/recommended.codegen.d.ts +2 -0
- package/dist/types-ts4.5/rules/index.codegen.d.ts +2 -0
- package/dist/types-ts4.5/rules/no-html-text-input/index.d.ts +3 -0
- package/dist/types-ts4.5/rules/no-html-text-input/node-types/index.d.ts +1 -0
- package/dist/types-ts4.5/rules/no-html-text-input/node-types/jsx-element/index.d.ts +8 -0
- package/dist/types-ts4.5/rules/no-html-text-input/node-types/supported.d.ts +7 -0
- package/dist/types-ts4.5/rules/no-html-textarea/index.d.ts +3 -0
- package/dist/types-ts4.5/rules/no-html-textarea/node-types/index.d.ts +2 -0
- package/dist/types-ts4.5/rules/no-html-textarea/node-types/jsx-element/index.d.ts +8 -0
- package/dist/types-ts4.5/rules/no-html-textarea/node-types/styled-component/index.d.ts +8 -0
- package/dist/types-ts4.5/rules/no-html-textarea/node-types/supported.d.ts +7 -0
- package/package.json +1 -1
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { createLintRule } from '../utils/create-rule';
|
|
2
|
+
import { JSXElement as _JSXElement } from './node-types';
|
|
3
|
+
var rule = createLintRule({
|
|
4
|
+
meta: {
|
|
5
|
+
name: 'no-html-text-input',
|
|
6
|
+
type: 'suggestion',
|
|
7
|
+
hasSuggestions: true,
|
|
8
|
+
docs: {
|
|
9
|
+
description: 'Discourage direct usage of HTML text input elements in favor of the Atlassian Design System textfield component.',
|
|
10
|
+
recommended: true,
|
|
11
|
+
severity: 'warn'
|
|
12
|
+
},
|
|
13
|
+
messages: {
|
|
14
|
+
noHtmlTextInput: "This <{{ name }}> should be replaced with a textfield component from the Atlassian Design System. ADS components include event tracking, ensure accessible implementations, and provide access to ADS styling features like design tokens."
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
create: function create(context) {
|
|
18
|
+
return {
|
|
19
|
+
// transforms <input type="range" css={...}> usages
|
|
20
|
+
JSXElement: function JSXElement(node) {
|
|
21
|
+
_JSXElement.lint(node, {
|
|
22
|
+
context: context
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
export default rule;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { JSXElement } from './jsx-element';
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
|
|
2
|
+
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
3
|
+
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
4
|
+
import { isNodeOfType } from 'eslint-codemod-utils';
|
|
5
|
+
import { getSourceCode } from '@atlaskit/eslint-utils/context-compat';
|
|
6
|
+
import * as ast from '../../../../ast-nodes';
|
|
7
|
+
import { isSupportedForLint } from '../supported';
|
|
8
|
+
function isImportDeclaration(node) {
|
|
9
|
+
return node.type === 'ImportDeclaration';
|
|
10
|
+
}
|
|
11
|
+
export var JSXElement = {
|
|
12
|
+
lint: function lint(node, _ref) {
|
|
13
|
+
var context = _ref.context;
|
|
14
|
+
if (!isSupportedForLint(node)) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
var nodeName = ast.JSXElement.getName(node);
|
|
18
|
+
var sourceCode = getSourceCode(context);
|
|
19
|
+
var importDeclarations = sourceCode.ast.body.filter(isImportDeclaration);
|
|
20
|
+
var existingTextfieldName = null;
|
|
21
|
+
var usedNames = new Set();
|
|
22
|
+
|
|
23
|
+
// Check for existing imports
|
|
24
|
+
var _iterator = _createForOfIteratorHelper(importDeclarations),
|
|
25
|
+
_step;
|
|
26
|
+
try {
|
|
27
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
28
|
+
var declaration = _step.value;
|
|
29
|
+
var _iterator2 = _createForOfIteratorHelper(declaration.specifiers),
|
|
30
|
+
_step2;
|
|
31
|
+
try {
|
|
32
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
33
|
+
var specifier = _step2.value;
|
|
34
|
+
usedNames.add(specifier.local.name);
|
|
35
|
+
}
|
|
36
|
+
} catch (err) {
|
|
37
|
+
_iterator2.e(err);
|
|
38
|
+
} finally {
|
|
39
|
+
_iterator2.f();
|
|
40
|
+
}
|
|
41
|
+
if (declaration.source.value === '@atlaskit/textfield') {
|
|
42
|
+
var defaultSpecifier = declaration.specifiers.find(function (specifier) {
|
|
43
|
+
return specifier.type === 'ImportDefaultSpecifier';
|
|
44
|
+
});
|
|
45
|
+
if (defaultSpecifier) {
|
|
46
|
+
existingTextfieldName = defaultSpecifier.local.name;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
} catch (err) {
|
|
51
|
+
_iterator.e(err);
|
|
52
|
+
} finally {
|
|
53
|
+
_iterator.f();
|
|
54
|
+
}
|
|
55
|
+
var generateUniqueName = function generateUniqueName(baseName) {
|
|
56
|
+
var index = 1;
|
|
57
|
+
var newName = baseName;
|
|
58
|
+
while (usedNames.has(newName)) {
|
|
59
|
+
newName = "".concat(baseName).concat(index);
|
|
60
|
+
index++;
|
|
61
|
+
}
|
|
62
|
+
return newName;
|
|
63
|
+
};
|
|
64
|
+
var textfieldName = existingTextfieldName || generateUniqueName('Textfield');
|
|
65
|
+
context.report({
|
|
66
|
+
node: node.openingElement,
|
|
67
|
+
messageId: 'noHtmlTextInput',
|
|
68
|
+
data: {
|
|
69
|
+
name: nodeName
|
|
70
|
+
},
|
|
71
|
+
suggest: [{
|
|
72
|
+
desc: 'Replace with Textfield component from @atlaskit/textfield',
|
|
73
|
+
fix: function fix(fixer) {
|
|
74
|
+
var _node$closingElement;
|
|
75
|
+
var openingTagRange = node.openingElement.range;
|
|
76
|
+
var closingTagRange = (_node$closingElement = node.closingElement) === null || _node$closingElement === void 0 ? void 0 : _node$closingElement.range;
|
|
77
|
+
var attributesText = node.openingElement.attributes.filter(function (attr) {
|
|
78
|
+
return !isNodeOfType(attr, 'JSXAttribute') || attr.name.name !== 'type';
|
|
79
|
+
}).map(function (attr) {
|
|
80
|
+
return sourceCode.getText(attr);
|
|
81
|
+
}).join(' ');
|
|
82
|
+
var fixers = [];
|
|
83
|
+
|
|
84
|
+
// Replace <img> with <textfield> and retain attributes
|
|
85
|
+
if (openingTagRange) {
|
|
86
|
+
if (node.openingElement.selfClosing) {
|
|
87
|
+
fixers.push(fixer.replaceTextRange([openingTagRange[0] + 1, openingTagRange[1] - 1], "".concat(textfieldName).concat(attributesText ? " ".concat(attributesText) : '', " /")));
|
|
88
|
+
} else {
|
|
89
|
+
fixers.push(fixer.replaceTextRange([openingTagRange[0] + 1, openingTagRange[1] - 1], "".concat(textfieldName).concat(attributesText ? " ".concat(attributesText) : '')));
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (closingTagRange && !node.openingElement.selfClosing) {
|
|
93
|
+
fixers.push(fixer.replaceTextRange([closingTagRange[0] + 2, closingTagRange[1] - 1], textfieldName));
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Add import if not present
|
|
97
|
+
if (!existingTextfieldName) {
|
|
98
|
+
var importStatement = "import ".concat(textfieldName, " from '@atlaskit/textfield';\n");
|
|
99
|
+
fixers.push(fixer.insertTextBefore(sourceCode.ast, importStatement));
|
|
100
|
+
}
|
|
101
|
+
return fixers;
|
|
102
|
+
}
|
|
103
|
+
}]
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { isNodeOfType } from 'eslint-codemod-utils';
|
|
2
|
+
import * as ast from '../../../ast-nodes';
|
|
3
|
+
var supportedElements = [{
|
|
4
|
+
name: 'input',
|
|
5
|
+
attributes: [{
|
|
6
|
+
name: 'type',
|
|
7
|
+
values: ['text'],
|
|
8
|
+
canBeUndefined: true
|
|
9
|
+
}]
|
|
10
|
+
}];
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Determines if the given JSX element is a supported element to lint with this rule.
|
|
14
|
+
*/
|
|
15
|
+
export function isSupportedForLint(jsxNode, elementName) {
|
|
16
|
+
if (!isNodeOfType(jsxNode, 'JSXElement')) {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Allow passing in the element name because the jsxNode doesn't
|
|
21
|
+
// represent the element name with styled components
|
|
22
|
+
var elName = elementName || ast.JSXElement.getName(jsxNode);
|
|
23
|
+
if (!elName) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Only check native HTML elements, not components
|
|
28
|
+
if (elName[0] !== elName[0].toLowerCase()) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
var supportedElement = supportedElements.find(function (_ref) {
|
|
32
|
+
var name = _ref.name;
|
|
33
|
+
return name === elName;
|
|
34
|
+
});
|
|
35
|
+
if (!supportedElement) {
|
|
36
|
+
supportedElement = supportedElements.find(function (_ref2) {
|
|
37
|
+
var name = _ref2.name;
|
|
38
|
+
return name === '*';
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
if (!supportedElement) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Check if the element has any attributes that are not supported
|
|
46
|
+
var attributes = ast.JSXElement.getAttributes(jsxNode);
|
|
47
|
+
if (supportedElement.attributes &&
|
|
48
|
+
// If not every attribute resolves to `true`
|
|
49
|
+
!supportedElement.attributes.every(function (_ref3) {
|
|
50
|
+
var name = _ref3.name,
|
|
51
|
+
values = _ref3.values,
|
|
52
|
+
canBeUndefined = _ref3.canBeUndefined;
|
|
53
|
+
// If it can be an undefined prop
|
|
54
|
+
if (canBeUndefined) {
|
|
55
|
+
// Search attributes for `name`
|
|
56
|
+
var foundAttribute = attributes.find(function (attr) {
|
|
57
|
+
return isNodeOfType(attr, 'JSXAttribute') && attr.name.name === name;
|
|
58
|
+
});
|
|
59
|
+
// If we didn't find that attribute, then it should be linted
|
|
60
|
+
if (!foundAttribute) {
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// If we did find the attribute with a matching name, then check if one of
|
|
66
|
+
// it's values matches
|
|
67
|
+
return attributes.some(function (attribute) {
|
|
68
|
+
// Don't lint spreads
|
|
69
|
+
if (attribute.type === 'JSXSpreadAttribute') {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
var isMatchingName = attribute.name.name === name;
|
|
73
|
+
var isMatchingValues = values && attribute.value && attribute.value.type === 'Literal' && typeof attribute.value.value === 'string' && (values === null || values === void 0 ? void 0 : values.includes(attribute.value.value));
|
|
74
|
+
|
|
75
|
+
// If one of our values match the attribute's value, lint it
|
|
76
|
+
return isMatchingName && isMatchingValues;
|
|
77
|
+
});
|
|
78
|
+
})) {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { createLintRule } from '../utils/create-rule';
|
|
2
|
+
import { JSXElement as _JSXElement, StyledComponent } from './node-types';
|
|
3
|
+
var rule = createLintRule({
|
|
4
|
+
meta: {
|
|
5
|
+
name: 'no-html-textarea',
|
|
6
|
+
type: 'suggestion',
|
|
7
|
+
hasSuggestions: true,
|
|
8
|
+
docs: {
|
|
9
|
+
description: 'Discourage direct usage of HTML textarea elements in favor of the Atlassian Design System textarea component.',
|
|
10
|
+
recommended: true,
|
|
11
|
+
severity: 'warn'
|
|
12
|
+
},
|
|
13
|
+
messages: {
|
|
14
|
+
noHtmlTextarea: "This <{{ name }}> should be replaced with a textarea component from the Atlassian Design System. ADS components include event tracking, ensure accessible implementations, and provide access to ADS styling features like design tokens."
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
create: function create(context) {
|
|
18
|
+
return {
|
|
19
|
+
// transforms styled.<textarea>(...) usages
|
|
20
|
+
CallExpression: function CallExpression(node) {
|
|
21
|
+
StyledComponent.lint(node, {
|
|
22
|
+
context: context
|
|
23
|
+
});
|
|
24
|
+
},
|
|
25
|
+
// transforms <textarea css={...}> usages
|
|
26
|
+
JSXElement: function JSXElement(node) {
|
|
27
|
+
_JSXElement.lint(node, {
|
|
28
|
+
context: context
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
export default rule;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
|
|
2
|
+
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
3
|
+
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
4
|
+
import { getSourceCode } from '@atlaskit/eslint-utils/context-compat';
|
|
5
|
+
import * as ast from '../../../../ast-nodes';
|
|
6
|
+
import { isSupportedForLint } from '../supported';
|
|
7
|
+
function isImportDeclaration(node) {
|
|
8
|
+
return node.type === 'ImportDeclaration';
|
|
9
|
+
}
|
|
10
|
+
export var JSXElement = {
|
|
11
|
+
lint: function lint(node, _ref) {
|
|
12
|
+
var context = _ref.context;
|
|
13
|
+
if (!isSupportedForLint(node)) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
var nodeName = ast.JSXElement.getName(node);
|
|
17
|
+
var sourceCode = getSourceCode(context);
|
|
18
|
+
var importDeclarations = sourceCode.ast.body.filter(isImportDeclaration);
|
|
19
|
+
var existingTextareaName = null;
|
|
20
|
+
var usedNames = new Set();
|
|
21
|
+
|
|
22
|
+
// Check for existing imports
|
|
23
|
+
var _iterator = _createForOfIteratorHelper(importDeclarations),
|
|
24
|
+
_step;
|
|
25
|
+
try {
|
|
26
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
27
|
+
var declaration = _step.value;
|
|
28
|
+
var _iterator2 = _createForOfIteratorHelper(declaration.specifiers),
|
|
29
|
+
_step2;
|
|
30
|
+
try {
|
|
31
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
32
|
+
var specifier = _step2.value;
|
|
33
|
+
usedNames.add(specifier.local.name);
|
|
34
|
+
}
|
|
35
|
+
} catch (err) {
|
|
36
|
+
_iterator2.e(err);
|
|
37
|
+
} finally {
|
|
38
|
+
_iterator2.f();
|
|
39
|
+
}
|
|
40
|
+
if (declaration.source.value === '@atlaskit/textarea') {
|
|
41
|
+
var defaultSpecifier = declaration.specifiers.find(function (specifier) {
|
|
42
|
+
return specifier.type === 'ImportDefaultSpecifier';
|
|
43
|
+
});
|
|
44
|
+
if (defaultSpecifier) {
|
|
45
|
+
existingTextareaName = defaultSpecifier.local.name;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
} catch (err) {
|
|
50
|
+
_iterator.e(err);
|
|
51
|
+
} finally {
|
|
52
|
+
_iterator.f();
|
|
53
|
+
}
|
|
54
|
+
var generateUniqueName = function generateUniqueName(baseName) {
|
|
55
|
+
var index = 1;
|
|
56
|
+
var newName = baseName;
|
|
57
|
+
while (usedNames.has(newName)) {
|
|
58
|
+
newName = "".concat(baseName).concat(index);
|
|
59
|
+
index++;
|
|
60
|
+
}
|
|
61
|
+
return newName;
|
|
62
|
+
};
|
|
63
|
+
var textareaName = existingTextareaName || generateUniqueName('Textarea');
|
|
64
|
+
context.report({
|
|
65
|
+
node: node.openingElement,
|
|
66
|
+
messageId: 'noHtmlTextarea',
|
|
67
|
+
data: {
|
|
68
|
+
name: nodeName
|
|
69
|
+
},
|
|
70
|
+
suggest: [{
|
|
71
|
+
desc: 'Replace with Textarea component from @atlaskit/textarea',
|
|
72
|
+
fix: function fix(fixer) {
|
|
73
|
+
var _node$closingElement;
|
|
74
|
+
var openingTagRange = node.openingElement.range;
|
|
75
|
+
var closingTagRange = (_node$closingElement = node.closingElement) === null || _node$closingElement === void 0 ? void 0 : _node$closingElement.range;
|
|
76
|
+
var attributesText = node.openingElement.attributes.map(function (attr) {
|
|
77
|
+
return sourceCode.getText(attr);
|
|
78
|
+
}).join(' ');
|
|
79
|
+
var fixers = [];
|
|
80
|
+
|
|
81
|
+
// Replace <textarea> with <Textarea> and retain attributes
|
|
82
|
+
if (openingTagRange) {
|
|
83
|
+
if (node.openingElement.selfClosing) {
|
|
84
|
+
fixers.push(fixer.replaceTextRange([openingTagRange[0] + 1, openingTagRange[1] - 1], "".concat(textareaName).concat(attributesText ? " ".concat(attributesText) : '', " /")));
|
|
85
|
+
} else {
|
|
86
|
+
fixers.push(fixer.replaceTextRange([openingTagRange[0] + 1, openingTagRange[1] - 1], "".concat(textareaName).concat(attributesText ? " ".concat(attributesText) : '')));
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (closingTagRange && !node.openingElement.selfClosing) {
|
|
90
|
+
fixers.push(fixer.replaceTextRange([closingTagRange[0] + 2, closingTagRange[1] - 1], textareaName));
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Add import if not present
|
|
94
|
+
if (!existingTextareaName) {
|
|
95
|
+
var importStatement = "import ".concat(textareaName, " from '@atlaskit/textarea';\n");
|
|
96
|
+
fixers.push(fixer.insertTextBefore(sourceCode.ast, importStatement));
|
|
97
|
+
}
|
|
98
|
+
return fixers;
|
|
99
|
+
}
|
|
100
|
+
}]
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/* eslint-disable @repo/internal/react/require-jsdoc */
|
|
2
|
+
|
|
3
|
+
import { isNodeOfType } from 'eslint-codemod-utils';
|
|
4
|
+
import { getScope } from '@atlaskit/eslint-utils/context-compat';
|
|
5
|
+
import { getJsxElementByName } from '../../../utils/get-jsx-element-by-name';
|
|
6
|
+
import { getStyledComponentCall } from '../../../utils/get-styled-component-call';
|
|
7
|
+
import { isSupportedForLint } from '../supported';
|
|
8
|
+
export var StyledComponent = {
|
|
9
|
+
lint: function lint(node, _ref) {
|
|
10
|
+
var _getJsxElementByName;
|
|
11
|
+
var context = _ref.context;
|
|
12
|
+
if (!isNodeOfType(node, 'CallExpression') || !isNodeOfType(node.callee, 'MemberExpression') || !isNodeOfType(node.callee.object, 'Identifier') || !isNodeOfType(node.callee.property, 'Identifier')) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
var styles = getStyledComponentCall(node);
|
|
16
|
+
var elementName = node.callee.property.name;
|
|
17
|
+
if (!styles || !isNodeOfType(styles.id, 'Identifier')) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
var jsxElement = (_getJsxElementByName = getJsxElementByName(styles.id.name, getScope(context, node))) === null || _getJsxElementByName === void 0 ? void 0 : _getJsxElementByName.parent;
|
|
21
|
+
if (!jsxElement) {
|
|
22
|
+
// If there's no JSX element, we can't determine if it's being used as an textarea or not
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
if (jsxElement && !isSupportedForLint(jsxElement, elementName)) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
context.report({
|
|
29
|
+
node: styles,
|
|
30
|
+
messageId: 'noHtmlTextarea',
|
|
31
|
+
data: {
|
|
32
|
+
name: node.callee.property.name
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { isNodeOfType } from 'eslint-codemod-utils';
|
|
2
|
+
import * as ast from '../../../ast-nodes';
|
|
3
|
+
var supportedElements = [{
|
|
4
|
+
name: 'textarea'
|
|
5
|
+
}];
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Determines if the given JSX element is a supported element to lint with this rule.
|
|
9
|
+
*/
|
|
10
|
+
export function isSupportedForLint(jsxNode, elementName) {
|
|
11
|
+
if (!isNodeOfType(jsxNode, 'JSXElement')) {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Allow passing in the element name because the jsxNode doesn't
|
|
16
|
+
// represent the element name with styled components
|
|
17
|
+
var elName = elementName || ast.JSXElement.getName(jsxNode);
|
|
18
|
+
if (!elName) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Only check native HTML elements, not components
|
|
23
|
+
if (elName[0] !== elName[0].toLowerCase()) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
var supportedElement = supportedElements.find(function (_ref) {
|
|
27
|
+
var name = _ref.name;
|
|
28
|
+
return name === elName;
|
|
29
|
+
});
|
|
30
|
+
if (!supportedElement) {
|
|
31
|
+
supportedElement = supportedElements.find(function (_ref2) {
|
|
32
|
+
var name = _ref2.name;
|
|
33
|
+
return name === '*';
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
if (!supportedElement) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Check if the element has any attributes that are not supported
|
|
41
|
+
var attributes = ast.JSXElement.getAttributes(jsxNode);
|
|
42
|
+
if (supportedElement.attributes && !supportedElement.attributes.every(function (_ref3) {
|
|
43
|
+
var name = _ref3.name,
|
|
44
|
+
values = _ref3.values;
|
|
45
|
+
return attributes.some(function (attribute) {
|
|
46
|
+
if (attribute.type === 'JSXSpreadAttribute') {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
var isMatchingName = attribute.name.name === name;
|
|
50
|
+
var isMatchingValues = values && attribute.value && attribute.value.type === 'Literal' && typeof attribute.value.value === 'string' && (values === null || values === void 0 ? void 0 : values.includes(attribute.value.value));
|
|
51
|
+
return isMatchingName && isMatchingValues;
|
|
52
|
+
});
|
|
53
|
+
})) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
@@ -41,6 +41,8 @@ export declare const plugin: {
|
|
|
41
41
|
'no-html-radio': import("eslint").Rule.RuleModule;
|
|
42
42
|
'no-html-range': import("eslint").Rule.RuleModule;
|
|
43
43
|
'no-html-select': import("eslint").Rule.RuleModule;
|
|
44
|
+
'no-html-text-input': import("eslint").Rule.RuleModule;
|
|
45
|
+
'no-html-textarea': import("eslint").Rule.RuleModule;
|
|
44
46
|
'no-invalid-css-map': import("eslint").Rule.RuleModule;
|
|
45
47
|
'no-keyframes-tagged-template-expression': import("eslint").Rule.RuleModule;
|
|
46
48
|
'no-legacy-icons': import("eslint").Rule.RuleModule;
|
|
@@ -101,6 +103,8 @@ export declare const plugin: {
|
|
|
101
103
|
'@atlaskit/design-system/no-html-radio': "warn";
|
|
102
104
|
'@atlaskit/design-system/no-html-range': "warn";
|
|
103
105
|
'@atlaskit/design-system/no-html-select': "warn";
|
|
106
|
+
'@atlaskit/design-system/no-html-text-input': "warn";
|
|
107
|
+
'@atlaskit/design-system/no-html-textarea': "warn";
|
|
104
108
|
'@atlaskit/design-system/no-invalid-css-map': ["error", {
|
|
105
109
|
allowedFunctionCalls: string[][];
|
|
106
110
|
}];
|
|
@@ -165,6 +169,8 @@ export declare const plugin: {
|
|
|
165
169
|
'@atlaskit/design-system/no-html-radio': "warn";
|
|
166
170
|
'@atlaskit/design-system/no-html-range': "warn";
|
|
167
171
|
'@atlaskit/design-system/no-html-select': "warn";
|
|
172
|
+
'@atlaskit/design-system/no-html-text-input': "warn";
|
|
173
|
+
'@atlaskit/design-system/no-html-textarea': "warn";
|
|
168
174
|
'@atlaskit/design-system/no-invalid-css-map': ["error", {
|
|
169
175
|
allowedFunctionCalls: string[][];
|
|
170
176
|
}];
|
|
@@ -222,6 +228,8 @@ export declare const plugin: {
|
|
|
222
228
|
'@atlaskit/design-system/no-html-radio': "warn";
|
|
223
229
|
'@atlaskit/design-system/no-html-range': "warn";
|
|
224
230
|
'@atlaskit/design-system/no-html-select': "warn";
|
|
231
|
+
'@atlaskit/design-system/no-html-text-input': "warn";
|
|
232
|
+
'@atlaskit/design-system/no-html-textarea': "warn";
|
|
225
233
|
'@atlaskit/design-system/no-invalid-css-map': ["error", {
|
|
226
234
|
allowedFunctionCalls: string[][];
|
|
227
235
|
}];
|
|
@@ -270,6 +278,8 @@ export declare const plugin: {
|
|
|
270
278
|
'@atlaskit/design-system/no-html-radio': "warn";
|
|
271
279
|
'@atlaskit/design-system/no-html-range': "warn";
|
|
272
280
|
'@atlaskit/design-system/no-html-select': "warn";
|
|
281
|
+
'@atlaskit/design-system/no-html-text-input': "warn";
|
|
282
|
+
'@atlaskit/design-system/no-html-textarea': "warn";
|
|
273
283
|
'@atlaskit/design-system/no-invalid-css-map': ["error", {
|
|
274
284
|
allowedFunctionCalls: string[][];
|
|
275
285
|
}];
|
|
@@ -324,6 +334,8 @@ declare const configs: {
|
|
|
324
334
|
'@atlaskit/design-system/no-html-radio': "warn";
|
|
325
335
|
'@atlaskit/design-system/no-html-range': "warn";
|
|
326
336
|
'@atlaskit/design-system/no-html-select': "warn";
|
|
337
|
+
'@atlaskit/design-system/no-html-text-input': "warn";
|
|
338
|
+
'@atlaskit/design-system/no-html-textarea': "warn";
|
|
327
339
|
'@atlaskit/design-system/no-invalid-css-map': ["error", {
|
|
328
340
|
allowedFunctionCalls: string[][];
|
|
329
341
|
}];
|
|
@@ -388,6 +400,8 @@ declare const configs: {
|
|
|
388
400
|
'@atlaskit/design-system/no-html-radio': "warn";
|
|
389
401
|
'@atlaskit/design-system/no-html-range': "warn";
|
|
390
402
|
'@atlaskit/design-system/no-html-select': "warn";
|
|
403
|
+
'@atlaskit/design-system/no-html-text-input': "warn";
|
|
404
|
+
'@atlaskit/design-system/no-html-textarea': "warn";
|
|
391
405
|
'@atlaskit/design-system/no-invalid-css-map': ["error", {
|
|
392
406
|
allowedFunctionCalls: string[][];
|
|
393
407
|
}];
|
|
@@ -445,6 +459,8 @@ declare const configs: {
|
|
|
445
459
|
'@atlaskit/design-system/no-html-radio': "warn";
|
|
446
460
|
'@atlaskit/design-system/no-html-range': "warn";
|
|
447
461
|
'@atlaskit/design-system/no-html-select': "warn";
|
|
462
|
+
'@atlaskit/design-system/no-html-text-input': "warn";
|
|
463
|
+
'@atlaskit/design-system/no-html-textarea': "warn";
|
|
448
464
|
'@atlaskit/design-system/no-invalid-css-map': ["error", {
|
|
449
465
|
allowedFunctionCalls: string[][];
|
|
450
466
|
}];
|
|
@@ -493,6 +509,8 @@ declare const configs: {
|
|
|
493
509
|
'@atlaskit/design-system/no-html-radio': "warn";
|
|
494
510
|
'@atlaskit/design-system/no-html-range': "warn";
|
|
495
511
|
'@atlaskit/design-system/no-html-select': "warn";
|
|
512
|
+
'@atlaskit/design-system/no-html-text-input': "warn";
|
|
513
|
+
'@atlaskit/design-system/no-html-textarea': "warn";
|
|
496
514
|
'@atlaskit/design-system/no-invalid-css-map': ["error", {
|
|
497
515
|
allowedFunctionCalls: string[][];
|
|
498
516
|
}];
|
|
@@ -24,6 +24,8 @@ declare const _default: {
|
|
|
24
24
|
'@atlaskit/design-system/no-html-radio': "warn";
|
|
25
25
|
'@atlaskit/design-system/no-html-range': "warn";
|
|
26
26
|
'@atlaskit/design-system/no-html-select': "warn";
|
|
27
|
+
'@atlaskit/design-system/no-html-text-input': "warn";
|
|
28
|
+
'@atlaskit/design-system/no-html-textarea': "warn";
|
|
27
29
|
'@atlaskit/design-system/no-invalid-css-map': ["error", {
|
|
28
30
|
allowedFunctionCalls: string[][];
|
|
29
31
|
}];
|
|
@@ -24,6 +24,8 @@ declare const _default: {
|
|
|
24
24
|
'@atlaskit/design-system/no-html-radio': "warn";
|
|
25
25
|
'@atlaskit/design-system/no-html-range': "warn";
|
|
26
26
|
'@atlaskit/design-system/no-html-select': "warn";
|
|
27
|
+
'@atlaskit/design-system/no-html-text-input': "warn";
|
|
28
|
+
'@atlaskit/design-system/no-html-textarea': "warn";
|
|
27
29
|
'@atlaskit/design-system/no-invalid-css-map': ["error", {
|
|
28
30
|
allowedFunctionCalls: string[][];
|
|
29
31
|
}];
|
|
@@ -19,6 +19,8 @@ declare const _default: {
|
|
|
19
19
|
'@atlaskit/design-system/no-html-radio': "warn";
|
|
20
20
|
'@atlaskit/design-system/no-html-range': "warn";
|
|
21
21
|
'@atlaskit/design-system/no-html-select': "warn";
|
|
22
|
+
'@atlaskit/design-system/no-html-text-input': "warn";
|
|
23
|
+
'@atlaskit/design-system/no-html-textarea': "warn";
|
|
22
24
|
'@atlaskit/design-system/no-invalid-css-map': ["error", {
|
|
23
25
|
allowedFunctionCalls: string[][];
|
|
24
26
|
}];
|
|
@@ -19,6 +19,8 @@ declare const _default: {
|
|
|
19
19
|
'@atlaskit/design-system/no-html-radio': "warn";
|
|
20
20
|
'@atlaskit/design-system/no-html-range': "warn";
|
|
21
21
|
'@atlaskit/design-system/no-html-select': "warn";
|
|
22
|
+
'@atlaskit/design-system/no-html-text-input': "warn";
|
|
23
|
+
'@atlaskit/design-system/no-html-textarea': "warn";
|
|
22
24
|
'@atlaskit/design-system/no-invalid-css-map': ["error", {
|
|
23
25
|
allowedFunctionCalls: string[][];
|
|
24
26
|
}];
|
|
@@ -25,6 +25,8 @@ export declare const rules: {
|
|
|
25
25
|
'no-html-radio': import("eslint").Rule.RuleModule;
|
|
26
26
|
'no-html-range': import("eslint").Rule.RuleModule;
|
|
27
27
|
'no-html-select': import("eslint").Rule.RuleModule;
|
|
28
|
+
'no-html-text-input': import("eslint").Rule.RuleModule;
|
|
29
|
+
'no-html-textarea': import("eslint").Rule.RuleModule;
|
|
28
30
|
'no-invalid-css-map': import("eslint").Rule.RuleModule;
|
|
29
31
|
'no-keyframes-tagged-template-expression': import("eslint").Rule.RuleModule;
|
|
30
32
|
'no-legacy-icons': import("eslint").Rule.RuleModule;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { JSXElement } from './jsx-element';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type EslintNode } from 'eslint-codemod-utils';
|
|
2
|
+
/**
|
|
3
|
+
* Determines if the given JSX element is a supported element to lint with this rule.
|
|
4
|
+
*/
|
|
5
|
+
export declare function isSupportedForLint(jsxNode: EslintNode, elementName?: string): jsxNode is Extract<EslintNode, {
|
|
6
|
+
type: 'JSXElement';
|
|
7
|
+
}>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type EslintNode } from 'eslint-codemod-utils';
|
|
2
|
+
/**
|
|
3
|
+
* Determines if the given JSX element is a supported element to lint with this rule.
|
|
4
|
+
*/
|
|
5
|
+
export declare function isSupportedForLint(jsxNode: EslintNode, elementName?: string): jsxNode is Extract<EslintNode, {
|
|
6
|
+
type: 'JSXElement';
|
|
7
|
+
}>;
|