eslint-plugin-orbit-components
Advanced tools
Comparing version 0.2.0 to 0.2.1
@@ -12,2 +12,4 @@ "use strict"; | ||
var _core = require("@babel/core"); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
@@ -22,3 +24,3 @@ | ||
var registerImport = function registerImport(context, node, name) { | ||
var registerImport = function registerImport(ctx, node, name) { | ||
if ((0, _isOrbitComponent.default)(name)) { | ||
@@ -32,19 +34,53 @@ var ORIGINAL_ORBIT_NAME = (0, _detectOriginalOrbitName.default)(node); | ||
return { | ||
JSXElement: function JSXElement(node) { | ||
JSXElement: function (_JSXElement) { | ||
function JSXElement(_x) { | ||
return _JSXElement.apply(this, arguments); | ||
} | ||
JSXElement.toString = function () { | ||
return _JSXElement.toString(); | ||
}; | ||
return JSXElement; | ||
}(function (node) { | ||
JSXElements.push(node); | ||
}, | ||
VariableDeclaration: function VariableDeclaration(node) { | ||
}), | ||
VariableDeclaration: function (_VariableDeclaration) { | ||
function VariableDeclaration(_x2) { | ||
return _VariableDeclaration.apply(this, arguments); | ||
} | ||
VariableDeclaration.toString = function () { | ||
return _VariableDeclaration.toString(); | ||
}; | ||
return VariableDeclaration; | ||
}(function (node) { | ||
node.declarations.forEach(function (declaration) { | ||
if (declaration.init && declaration.init.type === "ObjectExpression") { | ||
if (_core.types.isObjectExpression(declaration.init)) { | ||
if (declaration.init.properties.length > 0) { | ||
variables[declaration.id.name] = declaration.init.properties.map(function (property) { | ||
if (property.key && property.key.name) { | ||
return property.key.name; | ||
} | ||
}); | ||
if (_core.types.isIdentifier(declaration.id)) { | ||
variables[declaration.id.name] = declaration.init.properties.map(function (property) { | ||
if (_core.types.isProperty(property) && _core.types.isIdentifier(property.key)) { | ||
return property.key.name; | ||
} | ||
return null; | ||
}); | ||
} | ||
} | ||
} | ||
}); | ||
}, | ||
ImportDeclaration: function ImportDeclaration(node) { | ||
}), | ||
ImportDeclaration: function (_ImportDeclaration) { | ||
function ImportDeclaration(_x3) { | ||
return _ImportDeclaration.apply(this, arguments); | ||
} | ||
ImportDeclaration.toString = function () { | ||
return _ImportDeclaration.toString(); | ||
}; | ||
return ImportDeclaration; | ||
}(function (node) { | ||
if (node.specifiers.length) { | ||
@@ -54,56 +90,62 @@ var name = node.source.value; | ||
} | ||
}, | ||
}), | ||
"Program:exit": function ProgramExit() { | ||
JSXElements.forEach(function (node) { | ||
var localName = node.openingElement.name.name; | ||
if (_core.types.isJSXIdentifier(node.openingElement.name)) { | ||
var localName = node.openingElement.name.name; | ||
if (localName in importedOrbitComponents && Buttons.find(function (x) { | ||
return x === importedOrbitComponents[localName]; | ||
})) { | ||
/* | ||
if (localName in importedOrbitComponents && Buttons.find(function (x) { | ||
return x === importedOrbitComponents[localName]; | ||
})) { | ||
/* | ||
We can safely return, because the JSXElement is not selfClosing - does have children. | ||
e.g. <Button>children</Button> | ||
*/ | ||
if (!node.openingElement.selfClosing) return; | ||
/* | ||
*/ | ||
if (!node.openingElement.selfClosing) return; | ||
/* | ||
It's to possible to use rest spread to attach properties to components. | ||
Therefore, we need to check if `title` property is in the spreading object. | ||
*/ | ||
*/ | ||
var spread = node.openingElement.attributes.filter(function (n) { | ||
return n.type === "JSXSpreadAttribute"; | ||
}) || []; | ||
var spread = node.openingElement.attributes.filter(function (n) { | ||
return n.type === "JSXSpreadAttribute"; | ||
}) || []; | ||
if (spread.length > 0) { | ||
/* | ||
if (spread.length > 0) { | ||
/* | ||
The object can be imported from different file/module, | ||
therefore we skip empty object variable declarations | ||
*/ | ||
if (Object.keys(variables).length === 0) return; | ||
spread.forEach(function (s) { | ||
var name = s.argument.name; | ||
*/ | ||
if (Object.keys(variables).length === 0) return; | ||
spread.forEach(function (s) { | ||
if (_core.types.isJSXSpreadAttribute(s) && _core.types.isIdentifier(s.argument)) { | ||
var name = s.argument.name; | ||
/* | ||
If the spreading variable name is in object declarations, we can check if "title" | ||
is present, or report warning. | ||
*/ | ||
if (!(name in variables)) return; | ||
if (variables[name].find(function (v) { | ||
return v === "title"; | ||
})) return; | ||
context.report({ | ||
// @ts-expect-error TODO | ||
node: node, | ||
message: "".concat(localName, " doesn't have children. Please provide title property to add aria-label, so it's accessible for screen readers.") | ||
}); | ||
} | ||
}); | ||
/* | ||
If the spreading variable name is in object declarations, we can check if "title" | ||
is present, or report warning. | ||
*/ | ||
if (!(name in variables)) return; | ||
if (variables[name].find(function (v) { | ||
return v === "title"; | ||
})) return; | ||
Last check for JSX attributes, if "title" is present | ||
*/ | ||
} else if (!node.openingElement.attributes.find(function (n) { | ||
return n.type === "JSXAttribute" && n.name.name === "title"; | ||
})) { | ||
context.report({ | ||
// @ts-expect-error TODO | ||
node: node, | ||
message: "".concat(localName, " doesn't have children. Please provide title property to add aria-label, so it's accessible for screen readers.") | ||
}); | ||
}); | ||
/* | ||
Last check for JSX attributes, if "title" is present | ||
*/ | ||
} else if (!node.openingElement.attributes.find(function (n) { | ||
return n.type === "JSXAttribute" && n.name.name === "title"; | ||
})) { | ||
context.report({ | ||
node: node, | ||
message: "".concat(localName, " doesn't have children. Please provide title property to add aria-label, so it's accessible for screen readers.") | ||
}); | ||
} | ||
} | ||
@@ -110,0 +152,0 @@ } |
@@ -12,2 +12,4 @@ "use strict"; | ||
var _core = require("@babel/core"); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
@@ -17,11 +19,14 @@ | ||
create: function create(context) { | ||
var importedOrbitComponents = []; | ||
var importedOrbitComponents = {}; | ||
var JSXElements = []; | ||
var doNotUseTextIn = ["Button", "Heading"]; | ||
var registerImport = function registerImport(context, node, name) { | ||
var registerImport = function registerImport(ctx, node, name) { | ||
if ((0, _isOrbitComponent.default)(name)) { | ||
var ORIGINAL_ORBIT_NAME = (0, _detectOriginalOrbitName.default)(node); | ||
var LOCAL_NAME = node.specifiers[0].local.name; | ||
importedOrbitComponents[LOCAL_NAME] = ORIGINAL_ORBIT_NAME; | ||
if (ORIGINAL_ORBIT_NAME) { | ||
importedOrbitComponents[LOCAL_NAME] = ORIGINAL_ORBIT_NAME; | ||
} | ||
} | ||
@@ -31,6 +36,26 @@ }; | ||
return { | ||
JSXElement: function JSXElement(node) { | ||
JSXElement: function (_JSXElement) { | ||
function JSXElement(_x) { | ||
return _JSXElement.apply(this, arguments); | ||
} | ||
JSXElement.toString = function () { | ||
return _JSXElement.toString(); | ||
}; | ||
return JSXElement; | ||
}(function (node) { | ||
JSXElements.push(node); | ||
}, | ||
ImportDeclaration: function ImportDeclaration(node) { | ||
}), | ||
ImportDeclaration: function (_ImportDeclaration) { | ||
function ImportDeclaration(_x2) { | ||
return _ImportDeclaration.apply(this, arguments); | ||
} | ||
ImportDeclaration.toString = function () { | ||
return _ImportDeclaration.toString(); | ||
}; | ||
return ImportDeclaration; | ||
}(function (node) { | ||
if (node.specifiers.length) { | ||
@@ -40,20 +65,26 @@ var name = node.source.value; | ||
} | ||
}, | ||
}), | ||
"Program:exit": function ProgramExit() { | ||
JSXElements.forEach(function (node) { | ||
var localName = node.openingElement.name.name; | ||
if (_core.types.isJSXIdentifier(node.openingElement.name)) { | ||
var localName = node.openingElement.name.name; | ||
if (localName in importedOrbitComponents && doNotUseTextIn.find(function (x) { | ||
return x === importedOrbitComponents[localName]; | ||
}) && node.children) { | ||
{ | ||
if (localName in importedOrbitComponents && doNotUseTextIn.find(function (x) { | ||
return x === importedOrbitComponents[localName]; | ||
}) && node.children) { | ||
node.children.map(function (child) { | ||
if (!child.openingElement) return; | ||
var childElementName = child.openingElement.name.name; | ||
if (_core.types.isJSXElement(child)) { | ||
if (!child.openingElement) return; | ||
if (importedOrbitComponents[childElementName] === "Text") { | ||
context.report({ | ||
node: child, | ||
message: "Don't wrap ".concat(localName, "'s children to Text component. ") + "This wrapping in unnecessary and breaks visual style of ".concat(localName, "'s typography.") | ||
}); | ||
if (_core.types.isJSXIdentifier(child.openingElement.name)) { | ||
var childElementName = child.openingElement.name.name; | ||
if (importedOrbitComponents[childElementName] === "Text") { | ||
context.report({ | ||
// @ts-expect-error TODO | ||
node: child, | ||
message: "Don't wrap ".concat(localName, "'s children to Text component. ") + "This wrapping in unnecessary and breaks visual style of ".concat(localName, "'s typography.") | ||
}); | ||
} | ||
} | ||
} | ||
@@ -60,0 +91,0 @@ }); |
@@ -8,11 +8,13 @@ "use strict"; | ||
var _core = require("@babel/core"); | ||
var detectOriginalOrbitName = function detectOriginalOrbitName(node) { | ||
var specifier = node.specifiers[0]; // IF NAMED import | ||
if (specifier.imported) { | ||
if (_core.types.isImportSpecifier(specifier) && _core.types.isIdentifier(specifier.imported)) { | ||
return specifier.imported.name; | ||
} | ||
var originalImport = node.source.value.match(/@kiwicom\/orbit-components\/(?:lib|es)\/([^\/]*)/); | ||
return originalImport[1]; | ||
var originalImport = node.source.value.match(/@kiwicom\/orbit-components\/(?:lib|es)\/([^/]*)/); | ||
if (originalImport) return originalImport[1]; | ||
}; | ||
@@ -19,0 +21,0 @@ |
@@ -10,17 +10,17 @@ # button-has-title | ||
```jsx | ||
import Button from "@kiwicom/orbit-components/lib/Button" | ||
import Airplane from "@kiwicom/orbit-components/lib/icon/Airplane" | ||
import Button from "@kiwicom/orbit-components/lib/Button"; | ||
import Airplane from "@kiwicom/orbit-components/lib/icon/Airplane"; | ||
const App = () => <Button iconLeft={<Airplane />} /> | ||
const App = () => <Button iconLeft={<Airplane />} />; | ||
``` | ||
```jsx | ||
import Button from "@kiwicom/orbit-components/lib/Button" | ||
import Airplane from "@kiwicom/orbit-components/lib/icon/Airplane" | ||
import Button from "@kiwicom/orbit-components/lib/Button"; | ||
import Airplane from "@kiwicom/orbit-components/lib/icon/Airplane"; | ||
const buttonProps = { | ||
iconLeft: <Airplane />, | ||
fullWidth: true | ||
} | ||
const App = () => <Button {...buttonProps} /> | ||
fullWidth: true, | ||
}; | ||
const App = () => <Button {...buttonProps} />; | ||
``` | ||
@@ -31,18 +31,18 @@ | ||
```jsx | ||
import Button from "@kiwicom/orbit-components/lib/Button" | ||
import Airplane from "@kiwicom/orbit-components/lib/icon/Airplane" | ||
import Button from "@kiwicom/orbit-components/lib/Button"; | ||
import Airplane from "@kiwicom/orbit-components/lib/icon/Airplane"; | ||
const App = () => <Button title="Continue" iconLeft={<Airplane />} /> | ||
const App = () => <Button title="Continue" iconLeft={<Airplane />} />; | ||
``` | ||
```jsx | ||
import Button from "@kiwicom/orbit-components/lib/Button" | ||
import Button from "@kiwicom/orbit-components/lib/Button"; | ||
const App = () => <Button>Continue</Button> | ||
const App = () => <Button>Continue</Button>; | ||
``` | ||
```jsx | ||
import Button from "@kiwicom/orbit-components/lib/Button" | ||
import Button from "@kiwicom/orbit-components/lib/Button"; | ||
const ButtonWrapper = (props) => <Button {...props} /> | ||
const ButtonWrapper = props => <Button {...props} />; | ||
``` | ||
@@ -49,0 +49,0 @@ |
@@ -10,19 +10,21 @@ # unnecessary-text | ||
```jsx | ||
import Button from "@kiwicom/orbit-components/lib/Button" | ||
import OrbitText from "@kiwicom/orbit-components/lib/Text" | ||
import Button from "@kiwicom/orbit-components/lib/Button"; | ||
import OrbitText from "@kiwicom/orbit-components/lib/Text"; | ||
const Example = () => | ||
const Example = () => ( | ||
<Button> | ||
<OrbitText>Hello World!</OrbitText> | ||
</Button> | ||
); | ||
``` | ||
```jsx | ||
import Heading from "@kiwicom/orbit-components/lib/Heading" | ||
import OrbitText from "@kiwicom/orbit-components/lib/Text" | ||
import Heading from "@kiwicom/orbit-components/lib/Heading"; | ||
import OrbitText from "@kiwicom/orbit-components/lib/Text"; | ||
const Example = () => | ||
const Example = () => ( | ||
<Heading> | ||
<OrbitText>Hello World!</OrbitText> | ||
</Heading> | ||
); | ||
``` | ||
@@ -29,0 +31,0 @@ |
{ | ||
"name": "eslint-plugin-orbit-components", | ||
"version": "0.2.0", | ||
"description": "Collection of ESLint rules to enforce the best usage practices of @kiwicom/orbit-components", | ||
"version": "0.2.1", | ||
"author": "Kiwi.com", | ||
"main": "dist/index.js", | ||
"license": "MIT", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/kiwicom/eslint-plugin-orbit-components" | ||
"url": "https://github.com/kiwicom/orbit.git", | ||
"directory": "packages/eslint-plugin-orbit-components" | ||
}, | ||
"files": [ | ||
"dist", | ||
"docs", | ||
"package.json", | ||
"README.md", | ||
"yarn.lock" | ||
], | ||
"keywords": [ | ||
@@ -16,29 +27,11 @@ "eslint", | ||
], | ||
"author": "Kiwi.com", | ||
"main": "dist/index.js", | ||
"scripts": { | ||
"build": "rm -fr ./dist && babel ./src --out-dir ./dist", | ||
"test": "jest tests" | ||
"build": "rm -fr ./dist && babel ./src --extensions '.ts' --out-dir ./dist", | ||
"prepublishOnly": "yarn build" | ||
}, | ||
"files": [ | ||
"dist", | ||
"docs", | ||
"package.json", | ||
"README.md", | ||
"yarn.lock" | ||
], | ||
"devDependencies": { | ||
"@babel/cli": "^7.1.6", | ||
"@babel/core": "^7.1.6", | ||
"@babel/preset-env": "^7.1.6", | ||
"babel-core": "^7.0.0-bridge.0", | ||
"babel-eslint": "^10.0.1", | ||
"babel-jest": "^23.6.0", | ||
"eslint": "^5.9.0", | ||
"eslint-config-prettier": "^3.3.0", | ||
"eslint-plugin-prettier": "^3.0.0", | ||
"jest": "^23.6.0", | ||
"prettier": "^1.15.3" | ||
}, | ||
"license": "MIT" | ||
"@babel/preset-env": "^7.12.11", | ||
"@babel/preset-typescript": "^7.12.7", | ||
"@types/eslint": "^7.2.6" | ||
} | ||
} |
@@ -35,4 +35,4 @@ # eslint-plugin-orbit-components | ||
- [button-has-title](docs/rules/button-has-title.md): Enforces that `Button` and `ButtonLink` do have either `children` or `title` property. | ||
- [unnecessary-text](docs/rules/unnecessary-text.md): Enforces that children of `Button` or `Heading` are not wrapped in `Text` component. | ||
- [button-has-title](https://github.com/kiwicom/eslint-plugin-orbit-components/blob/master/docs/rules/button-has-title.md): Enforces that `Button` and `ButtonLink` do have either `children` or `title` property. | ||
- [unnecessary-text](https://github.com/kiwicom/eslint-plugin-orbit-components/blob/master/docs/rules/unnecessary-text.md): Enforces that children of `Button` or `Heading` are not wrapped in `Text` component. | ||
@@ -39,0 +39,0 @@ ## License |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
3
248
14526
1