Launch Week Day 5: Introducing Reachability for PHP.Learn More
Socket
Book a DemoSign in
Socket

eslint-plugin-i18next

Package Overview
Dependencies
Maintainers
1
Versions
55
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

eslint-plugin-i18next - npm Package Compare versions

Comparing version
2.3.0
to
3.2.0
+195
lib/constants.js
exports.DOM_TAGS = [
'a',
'abbr',
'acronym',
'address',
'applet',
'area',
'article',
'aside',
'audio',
'b',
'base',
'basefont',
'bdi',
'bdo',
'big',
'blockquote',
'body',
'br',
'button',
'canvas',
'caption',
'center',
'cite',
'code',
'col',
'colgroup',
'data',
'datalist',
'dd',
'del',
'details',
'dfn',
'dialog',
'dir',
'div',
'dl',
'dt',
'em',
'embed',
'fieldset',
'figcaption',
'figure',
'font',
'footer',
'form',
'frame',
'frameset',
'h1 to h6',
'head',
'header',
'hr',
'html',
'i',
'iframe',
'img',
'input',
'ins',
'kbd',
'label',
'legend',
'li',
'link',
'main',
'map',
'mark',
'meta',
'meter',
'nav',
'noframes',
'noscript',
'object',
'ol',
'optgroup',
'option',
'output',
'p',
'param',
'picture',
'pre',
'progress',
'q',
'rp',
'rt',
'ruby',
's',
'samp',
'script',
'section',
'select',
'small',
'source',
'span',
'strike',
'strong',
'style',
'sub',
'summary',
'sup',
'svg',
'table',
'tbody',
'td',
'template',
'textarea',
'tfoot',
'th',
'thead',
'time',
'title',
'tr',
'track',
'tt',
'u',
'ul',
'var',
'video',
'wbr'
];
exports.SVG_TAGS = [
'a',
'animate',
'animateMotion',
'animateTransform',
'circle',
'clipPath',
'color-profile',
'defs',
'desc',
'discard',
'ellipse',
'feBlend',
'feColorMatrix',
'feComponentTransfer',
'feComposite',
'feConvolveMatrix',
'feDiffuseLighting',
'feDisplacementMap',
'feDistantLight',
'feDropShadow',
'feFlood',
'feFuncA',
'feFuncB',
'feFuncG',
'feFuncR',
'feGaussianBlur',
'feImage',
'feMerge',
'feMergeNode',
'feMorphology',
'feOffset',
'fePointLight',
'feSpecularLighting',
'feSpotLight',
'feTile',
'feTurbulence',
'filter',
'foreignObject',
'g',
'hatch',
'hatchpath',
'image',
'line',
'linearGradient',
'marker',
'mask',
'mesh',
'meshgradient',
'meshpatch',
'meshrow',
'metadata',
'mpath',
'path',
'pattern',
'polygon',
'polyline',
'radialGradient',
'rect',
'script',
'set',
'solidcolor',
'stop',
'style',
'svg',
'switch',
'symbol',
'text',
'textPath',
'title',
'tspan',
'unknown',
'use',
'view'
];
+54
-0

@@ -5,2 +5,56 @@ # Changelog

## [3.2.0](https://github.com/edvardchen/eslint-plugin-i18next/compare/v3.1.1...v3.2.0) (2019-10-21)
### Features
* allow displayName property in classes ([5362281](https://github.com/edvardchen/eslint-plugin-i18next/commit/5362281))
### [3.1.1](https://github.com/edvardchen/eslint-plugin-i18next/compare/v3.1.0...v3.1.1) (2019-10-10)
### Bug Fixes
* add missing plugin in recommended config ([dde83ed](https://github.com/edvardchen/eslint-plugin-i18next/commit/dde83ed))
## [3.1.0](https://github.com/edvardchen/eslint-plugin-i18next/compare/v3.0.0...v3.1.0) (2019-10-10)
### Features
* ignore not-word string ([1752cbe](https://github.com/edvardchen/eslint-plugin-i18next/commit/1752cbe))
## [3.0.0](https://github.com/edvardchen/eslint-plugin-i18next/compare/v2.5.0...v3.0.0) (2019-10-09)
### ⚠ BREAKING CHANGES
* SInce the whitelist was cut short, it would complain when the removed attributes
were added to custom component like <Foo src="hello" />
### Features
* ignore most DOM attrs ([71483c2](https://github.com/edvardchen/eslint-plugin-i18next/commit/71483c2))
## [2.5.0](https://github.com/edvardchen/eslint-plugin-i18next/compare/v2.4.0...v2.5.0) (2019-10-08)
### Features
* add more ignored attributes and callee ([0f9e2ec](https://github.com/edvardchen/eslint-plugin-i18next/commit/0f9e2ec))
## [2.4.0](https://github.com/edvardchen/eslint-plugin-i18next/compare/v2.3.1...v2.4.0) (2019-10-08)
### Features
* add ignoreAttribute option ([c854313](https://github.com/edvardchen/eslint-plugin-i18next/commit/c854313))
### [2.3.1](https://github.com/edvardchen/eslint-plugin-i18next/compare/v2.3.0...v2.3.1) (2019-09-16)
### Bug Fixes
* whitelist addEventListener and few SVG attributes ([46241a6](https://github.com/edvardchen/eslint-plugin-i18next/commit/46241a6))
## [2.3.0](https://github.com/edvardchen/eslint-plugin-i18next/compare/v2.2.0...v2.3.0) (2019-07-26)

@@ -7,0 +61,0 @@

@@ -0,1 +1,3 @@

const { DOM_TAGS, SVG_TAGS } = require('./constants');
function isUpperCase(str) {

@@ -5,2 +7,20 @@ return /^[A-Z_-]+$/.test(str);

function isNativeDOMTag(str) {
return DOM_TAGS.includes(str);
}
function isSvgTag(str) {
return SVG_TAGS.includes(str);
}
const blacklistAttrs = ['placeholder', 'alt', 'aria-label', 'value'];
function isAllowedDOMAttr(tag, attr) {
if (isSvgTag(tag)) return true;
if (isNativeDOMTag(tag)) {
return !blacklistAttrs.includes(attr);
}
return false;
}
exports.isUpperCase = isUpperCase;
exports.isAllowedDOMAttr = isAllowedDOMAttr;
+1
-0

@@ -22,2 +22,3 @@ /**

recommended: {
plugins: ['i18next'],
rules: {

@@ -24,0 +25,0 @@ 'i18next/no-literal-string': [2]

@@ -7,3 +7,3 @@ /**

const { isUpperCase } = require('../helper');
const { isUpperCase, isAllowedDOMAttr } = require('../helper');
// const { TypeFlags, SyntaxKind } = require('typescript');

@@ -37,2 +37,8 @@

}
},
ignoreAttribute: {
type: 'array',
items: {
type: 'string'
}
}

@@ -51,5 +57,6 @@ },

} = context;
const whitelists = ((option && option.ignore) || []).map(
item => new RegExp(item)
);
const whitelists = [
/^[^A-Za-z]+$/, // ignore not-word string
...((option && option.ignore) || [])
].map(item => new RegExp(item));

@@ -78,8 +85,21 @@ const calleeWhitelists = generateCalleeWhitelists(option);

if (calleeName === 'require') return true;
return calleeWhitelists.simple.indexOf(calleeName) !== -1;
}
const atts = ['className', 'style', 'styleName', 'src', 'type', 'id'];
const ignoredClassProperties = ['displayName'];
const ignoredAttributes = (option && option.ignoreAttribute) || [];
const userJSXAttrs = [
'className',
'styleName',
'type',
'id',
'width',
'height',
...ignoredAttributes
];
function isValidAttrName(name) {
return atts.includes(name);
return userJSXAttrs.includes(name);
}

@@ -143,7 +163,15 @@

const parent = getNearestAncestor(node, 'JSXAttribute');
const attrName = parent.name.name;
// allow <div className="active" />
if (isValidAttrName(parent.name.name)) {
// allow <MyComponent className="active" />
if (isValidAttrName(attrName)) {
visited.add(node);
return;
}
const jsxElement = getNearestAncestor(node, 'JSXOpeningElement');
const tagName = jsxElement.name.name;
if (isAllowedDOMAttr(tagName, attrName)) {
visited.add(node);
}
},

@@ -174,2 +202,10 @@

'ClassProperty > Literal'(node) {
const { parent } = node;
if (parent.key && ignoredClassProperties.includes(parent.key.name)) {
visited.add(node);
}
},
'VariableDeclarator > Literal'(node) {

@@ -288,2 +324,6 @@ // allow statements like const A_B = "test"

const popularCallee = [
'addEventListener',
'removeEventListener',
'postMessage',
'getElementById',
//

@@ -297,3 +337,5 @@ // ─── VUEX CALLEE ────────────────────────────────────────────────────────────────

'includes',
'indexOf'
'indexOf',
'endsWith',
'startsWith'
];

@@ -300,0 +342,0 @@ function generateCalleeWhitelists(option) {

{
"name": "eslint-plugin-i18next",
"version": "2.3.0",
"version": "3.2.0",
"description": "ESLint plugin for i18n",

@@ -35,3 +35,5 @@ "keywords": [

"husky": "^1.3.1",
"lint-staged": "^9.4.2",
"mocha": "^6.1.4",
"prettier": "^1.18.2",
"typescript": "^3.5.2",

@@ -43,4 +45,11 @@ "vue-eslint-parser": "^6.0.3"

},
"lint-staged": {
"*.js": [
"prettier --write",
"git add"
]
},
"husky": {
"hooks": {
"pre-commit": "lint-staged",
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"

@@ -47,0 +56,0 @@ }

@@ -189,2 +189,16 @@ # eslint-plugin-i18next

#### SwithCase
Skip switchcase statement:
```typescript
// correct
switch (type) {
case 'foo':
break;
case 'bar':
break;
}
```
### Options

@@ -215,1 +229,12 @@

```
#### ignoreAttribute
The `ignoreAttribute` option specifies exceptions not to check for JSX attributes that match one of ignored attributes.
Examples of correct code for the `{ "ignoreAttribute": ["foo"] }` option:
```jsx
/*eslint i18next/no-literal-string: ["error", { "ignoreAttribute": ["foo"] }]*/
const element = <div foo="bar" />;
```

@@ -38,4 +38,16 @@ /**

{ code: 'a.includes("ios")' },
{ code: 'a.startsWith("ios")' },
{ code: 'a.endsWith("@gmail.com")' },
{ code: 'export * from "hello_export_all";' },
{ code: 'export { a } from "hello_export";' },
{
code:
'document.addEventListener("click", (event) => { event.preventDefault() })'
},
{
code:
'document.removeEventListener("click", (event) => { event.preventDefault() })'
},
{ code: 'window.postMessage("message", "*")' },
{ code: 'document.getElementById("some-id")' },
{ code: 'require("hello");' },

@@ -45,2 +57,4 @@ { code: 'const a = require(["hello"]);' },

{ code: 'const a = 1;' },
{ code: 'const a = "?";' },
{ code: `const a = "0123456789!@#$%^&*()_+|~-=\`[]{};':\\",./<>?";` },
{ code: 'i18n("hello");' },

@@ -59,6 +73,25 @@ { code: 'dispatch("hello");' },

{ code: 'var a = {foo: "FOO"};' },
{ code: 'class Form extends Component { displayName = "FormContainer" };' },
// JSX
{ code: '<div className="primary"></div>' },
{ code: '<div className={a ? "active": "inactive"}></div>' },
{ code: '<div>{i18next.t("foo")}</div>' }
{ code: '<div>{i18next.t("foo")}</div>' },
{ code: '<svg viewBox="0 0 20 40"></svg>' },
{ code: '<line x1="0" y1="0" x2="10" y2="20" />' },
{ code: '<path d="M10 10" />' },
{
code:
'<circle width="16px" height="16px" cx="10" cy="10" r="2" fill="red" />'
},
{
code:
'<a href="https://google.com" target="_blank" rel="noreferrer noopener"></a>'
},
{
code: '<div id="some-id" tabIndex="0" aria-labelledby="label-id"></div>'
},
{ code: '<div role="button"></div>' },
{ code: '<img src="./image.png" />' },
{ code: '<button type="button" for="form-id" />' },
{ code: '<DIV foo="bar" />', options: [{ ignoreAttribute: ['foo'] }] }
],

@@ -77,5 +110,9 @@

{ code: 'const a = "afoo";', options: [{ ignore: ['^foo'] }], errors },
{ code: 'class Form extends Component { property = "Something" };', errors },
// JSX
{ code: '<div>foo</div>', errors },
{ code: '<div>FOO</div>', errors }
{ code: '<div>FOO</div>', errors },
{ code: '<DIV foo="bar" />', errors },
{ code: '<img src="./image.png" alt="some-image" />', errors },
{ code: '<button aria-label="Close" type="button" />', errors }
]

@@ -82,0 +119,0 @@ });