eslint-plugin-ember
Advanced tools
Comparing version 4.1.3 to 4.2.0
@@ -7,2 +7,9 @@ ## Use `Ember.get` and `Ember.set` | ||
Ember tests use `this.get()` and `this.set()` as test helpers, so uses of them in the `tests` directory will not be reported. | ||
In addition, all files in the `mirage` directory will be excluded from this rule. | ||
This rule can be used with `eslint --fix` to automatically fix some occurrences. | ||
To be auto-fixed, `Ember` must be imported. | ||
Ideally, you should also be using [local modules](./local-modules.md); otherwise, the fixed code will look like `Ember.get(this, fooProperty')` instead of `get(this, 'fooProperty')`. | ||
```javascript | ||
@@ -9,0 +16,0 @@ // Bad |
@@ -13,2 +13,3 @@ /* | ||
"ember/named-functions-in-promises": "error", | ||
"ember/new-module-imports": "off", | ||
"ember/no-attrs-in-components": "off", | ||
@@ -15,0 +16,0 @@ "ember/no-attrs-snapshot": "error", |
'use strict'; | ||
const path = require('path'); | ||
const ember = require('../utils/ember'); | ||
const utils = require('../utils/utils'); | ||
const collectObjectPatternBindings = utils.collectObjectPatternBindings; | ||
const isIdentifier = utils.isIdentifier; | ||
const isThisExpression = utils.isThisExpression; | ||
//------------------------------------------------------------------------------ | ||
@@ -16,13 +22,47 @@ // General - use get and set | ||
}, | ||
fixable: null, // or "code" or "whitespace" | ||
fixable: 'code', | ||
}, | ||
create(context) { | ||
let emberImportAliasName; | ||
// Populated during VariableDeclarator traversal | ||
const localModulesPresent = {}; | ||
const sourceCode = context.getSourceCode(); | ||
const filename = context.getFilename(); | ||
const message = 'Use get/set'; | ||
const report = function (node) { | ||
context.report(node, message); | ||
}; | ||
function isFileInDirectory(dirname) { | ||
const pathParts = filename.split(path.sep); | ||
return pathParts.indexOf(dirname) > -1; | ||
} | ||
const avoidedProperties = [ | ||
function report(node) { | ||
context.report({ | ||
node: node.callee.property, | ||
message, | ||
fix(fixer) { | ||
if (!emberImportAliasName) { | ||
return null; | ||
} | ||
// this.set('foo', 3); | ||
// └┬─┘ └┬┘ └───┬──┘ | ||
// │ │ └─────── args | ||
// │ └────────────── method | ||
// └─────────────────── subject | ||
const subject = sourceCode.getText(node.callee.object); | ||
const method = sourceCode.getText(node.callee.property); | ||
const args = node.arguments.map(a => sourceCode.getText(a)).join(', '); | ||
const localModule = localModulesPresent[method]; | ||
const replacementMethod = localModule || `${emberImportAliasName}.${method}`; | ||
const fixedSource = `${replacementMethod}(${subject}, ${args})`; | ||
return fixer.replaceText(node, fixedSource); | ||
} | ||
}); | ||
} | ||
const avoidedMethods = [ | ||
'get', | ||
@@ -35,13 +75,55 @@ 'set', | ||
const testMethodsToSkip = [ | ||
'get', | ||
'set', | ||
]; | ||
const directoriesToSkipCompletely = [ | ||
'mirage', | ||
]; | ||
if (directoriesToSkipCompletely.some(dir => isFileInDirectory(dir))) { | ||
return {}; | ||
} | ||
return { | ||
MemberExpression(node) { | ||
ImportDeclaration(node) { | ||
emberImportAliasName = ember.getEmberImportAliasName(node); | ||
}, | ||
VariableDeclarator(node) { | ||
const isEmberImported = !!emberImportAliasName; | ||
const isModuleScope = context.getScope().type === 'module'; | ||
if (isEmberImported && isModuleScope) { | ||
// Populate localModulesPresent as a mapping of (avoided method -> local module alias) | ||
avoidedMethods.forEach((methodName) => { | ||
const destructuredAssignment = collectObjectPatternBindings(node, { | ||
[emberImportAliasName]: [methodName] | ||
}).pop(); | ||
if (destructuredAssignment) { | ||
localModulesPresent[methodName] = destructuredAssignment; | ||
} | ||
}); | ||
} | ||
}, | ||
CallExpression(node) { | ||
const callee = node.callee; | ||
const method = callee.property; | ||
// Skip this.get() and this.set() in tests/ | ||
if ( | ||
utils.isIdentifier(node.property) && | ||
avoidedProperties.indexOf(node.property.name) > -1 | ||
isFileInDirectory('tests') && | ||
isThisExpression(callee.object) && | ||
isIdentifier(method) && testMethodsToSkip.indexOf(method.name) > -1 | ||
) { | ||
report(node.property); | ||
return; | ||
} | ||
}, | ||
if (isIdentifier(method) && avoidedMethods.indexOf(method.name) > -1) { | ||
report(node); | ||
} | ||
} | ||
}; | ||
} | ||
}; |
{ | ||
"name": "eslint-plugin-ember", | ||
"version": "4.1.3", | ||
"version": "4.2.0", | ||
"description": "Eslint plugin for Ember.js apps", | ||
@@ -64,3 +64,6 @@ "main": "lib/index.js", | ||
] | ||
}, | ||
"publishConfig": { | ||
"tag": "latest" | ||
} | ||
} |
@@ -98,2 +98,3 @@ # eslint-plugin-ember | ||
| :white_check_mark: | [named-functions-in-promises](./docs/rules/named-functions-in-promises.md) | Enforces usage of named functions in promises | | ||
| | [new-module-imports](./docs/rules/new-module-imports.md) | Use "New Module Imports" from Ember RFC #176 | | ||
| | [no-attrs-in-components](./docs/rules/no-attrs-in-components.md) | Disallow usage of this.attrs in components | | ||
@@ -106,3 +107,3 @@ | :white_check_mark: | [no-function-prototype-extensions](./docs/rules/no-function-prototype-extensions.md) | Prevents usage of Ember's `function` prototype extensions | | ||
| :white_check_mark: | [use-brace-expansion](./docs/rules/use-brace-expansion.md) | Enforces usage of brace expansion | | ||
| :white_check_mark: | [use-ember-get-and-set](./docs/rules/use-ember-get-and-set.md) | Enforces usage of Ember.get and Ember.set | | ||
| :white_check_mark: :wrench: | [use-ember-get-and-set](./docs/rules/use-ember-get-and-set.md) | Enforces usage of Ember.get and Ember.set | | ||
@@ -109,0 +110,0 @@ |
@@ -25,89 +25,335 @@ // ------------------------------------------------------------------------------ | ||
'getWithDefault(controller, "test", "default")', | ||
{ | ||
code: 'this.get("myProperty")', | ||
filename: 'app/tests/unit/components/component-test.js', | ||
}, | ||
{ | ||
code: 'this.set("myProperty", "value")', | ||
filename: 'app/tests/unit/components/component-test.js', | ||
}, | ||
{ | ||
code: 'this.get("/resources")', | ||
filename: 'app/mirage/config.js', | ||
}, | ||
], | ||
invalid: [ | ||
// Non-fixable errors | ||
{ | ||
code: 'this.get("test")', | ||
errors: [{ | ||
message: 'Use get/set', | ||
}], | ||
output: 'this.get("test")', | ||
errors: [{ message: 'Use get/set' }], | ||
}, | ||
{ | ||
code: 'controller.get("test")', | ||
errors: [{ | ||
message: 'Use get/set', | ||
}], | ||
output: 'controller.get("test")', | ||
errors: [{ message: 'Use get/set' }], | ||
}, | ||
{ | ||
code: 'model.get("test")', | ||
errors: [{ | ||
message: 'Use get/set', | ||
}], | ||
output: 'model.get("test")', | ||
errors: [{ message: 'Use get/set' }], | ||
}, | ||
{ | ||
code: 'this.foo.get("test")', | ||
output: 'this.foo.get("test")', | ||
errors: [{ message: 'Use get/set' }], | ||
}, | ||
{ | ||
code: 'this.getWithDefault("test", "default")', | ||
errors: [{ | ||
message: 'Use get/set', | ||
}], | ||
output: 'this.getWithDefault("test", "default")', | ||
errors: [{ message: 'Use get/set' }], | ||
}, | ||
{ | ||
code: 'controller.getWithDefault("test", "default")', | ||
errors: [{ | ||
message: 'Use get/set', | ||
}], | ||
output: 'controller.getWithDefault("test", "default")', | ||
errors: [{ message: 'Use get/set' }], | ||
}, | ||
{ | ||
code: 'this.set("test", "value")', | ||
errors: [{ | ||
message: 'Use get/set', | ||
}], | ||
output: 'this.set("test", "value")', | ||
errors: [{ message: 'Use get/set' }], | ||
}, | ||
{ | ||
code: 'controller.set("test", "value")', | ||
errors: [{ | ||
message: 'Use get/set', | ||
}], | ||
output: 'controller.set("test", "value")', | ||
errors: [{ message: 'Use get/set' }], | ||
}, | ||
{ | ||
code: 'model.set("test", "value")', | ||
errors: [{ | ||
message: 'Use get/set', | ||
}], | ||
output: 'model.set("test", "value")', | ||
errors: [{ message: 'Use get/set' }], | ||
}, | ||
{ | ||
code: 'this.getProperties("test", "test2")', | ||
errors: [{ | ||
message: 'Use get/set', | ||
}], | ||
output: 'this.getProperties("test", "test2")', | ||
errors: [{ message: 'Use get/set' }], | ||
}, | ||
{ | ||
code: 'controller.getProperties("test", "test2")', | ||
errors: [{ | ||
message: 'Use get/set', | ||
}], | ||
output: 'controller.getProperties("test", "test2")', | ||
errors: [{ message: 'Use get/set' }], | ||
}, | ||
{ | ||
code: 'model.getProperties("test", "test2")', | ||
errors: [{ | ||
message: 'Use get/set', | ||
}], | ||
output: 'model.getProperties("test", "test2")', | ||
errors: [{ message: 'Use get/set' }], | ||
}, | ||
{ | ||
code: 'this.setProperties({test: "value"})', | ||
errors: [{ | ||
message: 'Use get/set', | ||
}], | ||
output: 'this.setProperties({test: "value"})', | ||
errors: [{ message: 'Use get/set' }], | ||
}, | ||
{ | ||
code: 'controller.setProperties({test: "value"})', | ||
errors: [{ | ||
message: 'Use get/set', | ||
}], | ||
output: 'controller.setProperties({test: "value"})', | ||
errors: [{ message: 'Use get/set' }], | ||
}, | ||
{ | ||
code: 'model.setProperties({test: "value"})', | ||
errors: [{ | ||
message: 'Use get/set', | ||
}], | ||
output: 'model.setProperties({test: "value"})', | ||
errors: [{ message: 'Use get/set' }], | ||
}, | ||
{ | ||
code: 'controller.getProperties("test", "test2")', | ||
filename: 'app/tests/unit/controllers/controller-test.js', | ||
output: 'controller.getProperties("test", "test2")', | ||
errors: [{ message: 'Use get/set' }], | ||
}, | ||
{ | ||
code: 'controller.setProperties({test: "value"})', | ||
filename: 'app/tests/unit/controllers/controller-test.js', | ||
output: 'controller.setProperties({test: "value"})', | ||
errors: [{ message: 'Use get/set' }], | ||
}, | ||
{ | ||
code: 'controller.getWithDefault("test", "default")', | ||
filename: 'app/tests/unit/controllers/controller-test.js', | ||
output: 'controller.getWithDefault("test", "default")', | ||
errors: [{ message: 'Use get/set' }], | ||
}, | ||
// Fixable errors using local modules | ||
{ | ||
code: 'import Ember from "ember"; const { get } = Ember; this.get("test")', | ||
output: 'import Ember from "ember"; const { get } = Ember; get(this, "test")', | ||
errors: [{ message: 'Use get/set' }], | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
}, | ||
{ | ||
code: 'import Ember from "ember"; const { get } = Ember; controller.get("test")', | ||
output: 'import Ember from "ember"; const { get } = Ember; get(controller, "test")', | ||
errors: [{ message: 'Use get/set' }], | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
}, | ||
{ | ||
code: 'import Ember from "ember"; const { get } = Ember; model.get("test")', | ||
output: 'import Ember from "ember"; const { get } = Ember; get(model, "test")', | ||
errors: [{ message: 'Use get/set' }], | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
}, | ||
{ | ||
code: 'import Ember from "ember"; const { get } = Ember; this.foo.get("test")', | ||
output: 'import Ember from "ember"; const { get } = Ember; get(this.foo, "test")', | ||
errors: [{ message: 'Use get/set' }], | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
}, | ||
{ | ||
code: 'import Ember from "ember"; const { getWithDefault } = Ember; this.getWithDefault("test", "default")', | ||
output: 'import Ember from "ember"; const { getWithDefault } = Ember; getWithDefault(this, "test", "default")', | ||
errors: [{ message: 'Use get/set' }], | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
}, | ||
{ | ||
code: 'import Ember from "ember"; const { getWithDefault } = Ember; controller.getWithDefault("test", "default")', | ||
output: 'import Ember from "ember"; const { getWithDefault } = Ember; getWithDefault(controller, "test", "default")', | ||
errors: [{ message: 'Use get/set' }], | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
}, | ||
{ | ||
code: 'import Ember from "ember"; const { set } = Ember; this.set("test", "value")', | ||
output: 'import Ember from "ember"; const { set } = Ember; set(this, "test", "value")', | ||
errors: [{ message: 'Use get/set' }], | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
}, | ||
{ | ||
code: 'import Ember from "ember"; const { set } = Ember; controller.set("test", "value")', | ||
output: 'import Ember from "ember"; const { set } = Ember; set(controller, "test", "value")', | ||
errors: [{ message: 'Use get/set' }], | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
}, | ||
{ | ||
code: 'import Ember from "ember"; const { set } = Ember; model.set("test", "value")', | ||
output: 'import Ember from "ember"; const { set } = Ember; set(model, "test", "value")', | ||
errors: [{ message: 'Use get/set' }], | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
}, | ||
{ | ||
code: 'import Ember from "ember"; const { getProperties } = Ember; this.getProperties("test", "test2")', | ||
output: 'import Ember from "ember"; const { getProperties } = Ember; getProperties(this, "test", "test2")', | ||
errors: [{ message: 'Use get/set' }], | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
}, | ||
{ | ||
code: 'import Ember from "ember"; const { getProperties } = Ember; controller.getProperties("test", "test2")', | ||
output: 'import Ember from "ember"; const { getProperties } = Ember; getProperties(controller, "test", "test2")', | ||
errors: [{ message: 'Use get/set' }], | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
}, | ||
{ | ||
code: 'import Ember from "ember"; const { getProperties } = Ember; model.getProperties("test", "test2")', | ||
output: 'import Ember from "ember"; const { getProperties } = Ember; getProperties(model, "test", "test2")', | ||
errors: [{ message: 'Use get/set' }], | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
}, | ||
{ | ||
code: 'import Ember from "ember"; const { setProperties } = Ember; this.setProperties({test: "value"})', | ||
output: 'import Ember from "ember"; const { setProperties } = Ember; setProperties(this, {test: "value"})', | ||
errors: [{ message: 'Use get/set' }], | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
}, | ||
{ | ||
code: 'import Ember from "ember"; const { setProperties } = Ember; controller.setProperties({test: "value"})', | ||
output: 'import Ember from "ember"; const { setProperties } = Ember; setProperties(controller, {test: "value"})', | ||
errors: [{ message: 'Use get/set' }], | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
}, | ||
{ | ||
code: 'import Ember from "ember"; const { setProperties } = Ember; model.setProperties({test: "value"})', | ||
output: 'import Ember from "ember"; const { setProperties } = Ember; setProperties(model, {test: "value"})', | ||
errors: [{ message: 'Use get/set' }], | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
}, | ||
{ | ||
code: 'import Ember from "ember"; const { getProperties } = Ember; controller.getProperties("test", "test2")', | ||
filename: 'app/tests/unit/controllers/controller-test.js', | ||
output: 'import Ember from "ember"; const { getProperties } = Ember; getProperties(controller, "test", "test2")', | ||
errors: [{ message: 'Use get/set' }], | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
}, | ||
{ | ||
code: 'import Ember from "ember"; const { setProperties } = Ember; controller.setProperties({test: "value"})', | ||
filename: 'app/tests/unit/controllers/controller-test.js', | ||
output: 'import Ember from "ember"; const { setProperties } = Ember; setProperties(controller, {test: "value"})', | ||
errors: [{ message: 'Use get/set' }], | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
}, | ||
{ | ||
code: 'import Ember from "ember"; const { getWithDefault } = Ember; controller.getWithDefault("test", "default")', | ||
filename: 'app/tests/unit/controllers/controller-test.js', | ||
output: 'import Ember from "ember"; const { getWithDefault } = Ember; getWithDefault(controller, "test", "default")', | ||
errors: [{ message: 'Use get/set' }], | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
}, | ||
// Fixable errors using method on Ember | ||
{ | ||
code: 'import Ember from "ember"; this.get("test")', | ||
output: 'import Ember from "ember"; Ember.get(this, "test")', | ||
errors: [{ message: 'Use get/set' }], | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
}, | ||
{ | ||
code: 'import Ember from "ember"; controller.get("test")', | ||
output: 'import Ember from "ember"; Ember.get(controller, "test")', | ||
errors: [{ message: 'Use get/set' }], | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
}, | ||
{ | ||
code: 'import Ember from "ember"; model.get("test")', | ||
output: 'import Ember from "ember"; Ember.get(model, "test")', | ||
errors: [{ message: 'Use get/set' }], | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
}, | ||
{ | ||
code: 'import Ember from "ember"; this.foo.get("test")', | ||
output: 'import Ember from "ember"; Ember.get(this.foo, "test")', | ||
errors: [{ message: 'Use get/set' }], | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
}, | ||
{ | ||
code: 'import Ember from "ember"; this.getWithDefault("test", "default")', | ||
output: 'import Ember from "ember"; Ember.getWithDefault(this, "test", "default")', | ||
errors: [{ message: 'Use get/set' }], | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
}, | ||
{ | ||
code: 'import Ember from "ember"; controller.getWithDefault("test", "default")', | ||
output: 'import Ember from "ember"; Ember.getWithDefault(controller, "test", "default")', | ||
errors: [{ message: 'Use get/set' }], | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
}, | ||
{ | ||
code: 'import Ember from "ember"; this.set("test", "value")', | ||
output: 'import Ember from "ember"; Ember.set(this, "test", "value")', | ||
errors: [{ message: 'Use get/set' }], | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
}, | ||
{ | ||
code: 'import Ember from "ember"; controller.set("test", "value")', | ||
output: 'import Ember from "ember"; Ember.set(controller, "test", "value")', | ||
errors: [{ message: 'Use get/set' }], | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
}, | ||
{ | ||
code: 'import Ember from "ember"; model.set("test", "value")', | ||
output: 'import Ember from "ember"; Ember.set(model, "test", "value")', | ||
errors: [{ message: 'Use get/set' }], | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
}, | ||
{ | ||
code: 'import Ember from "ember"; this.getProperties("test", "test2")', | ||
output: 'import Ember from "ember"; Ember.getProperties(this, "test", "test2")', | ||
errors: [{ message: 'Use get/set' }], | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
}, | ||
{ | ||
code: 'import Ember from "ember"; controller.getProperties("test", "test2")', | ||
output: 'import Ember from "ember"; Ember.getProperties(controller, "test", "test2")', | ||
errors: [{ message: 'Use get/set' }], | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
}, | ||
{ | ||
code: 'import Ember from "ember"; model.getProperties("test", "test2")', | ||
output: 'import Ember from "ember"; Ember.getProperties(model, "test", "test2")', | ||
errors: [{ message: 'Use get/set' }], | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
}, | ||
{ | ||
code: 'import Ember from "ember"; this.setProperties({test: "value"})', | ||
output: 'import Ember from "ember"; Ember.setProperties(this, {test: "value"})', | ||
errors: [{ message: 'Use get/set' }], | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
}, | ||
{ | ||
code: 'import Ember from "ember"; controller.setProperties({test: "value"})', | ||
output: 'import Ember from "ember"; Ember.setProperties(controller, {test: "value"})', | ||
errors: [{ message: 'Use get/set' }], | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
}, | ||
{ | ||
code: 'import Ember from "ember"; model.setProperties({test: "value"})', | ||
output: 'import Ember from "ember"; Ember.setProperties(model, {test: "value"})', | ||
errors: [{ message: 'Use get/set' }], | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
}, | ||
{ | ||
code: 'import Ember from "ember"; controller.getProperties("test", "test2")', | ||
filename: 'app/tests/unit/controllers/controller-test.js', | ||
output: 'import Ember from "ember"; Ember.getProperties(controller, "test", "test2")', | ||
errors: [{ message: 'Use get/set' }], | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
}, | ||
{ | ||
code: 'import Ember from "ember"; controller.setProperties({test: "value"})', | ||
filename: 'app/tests/unit/controllers/controller-test.js', | ||
output: 'import Ember from "ember"; Ember.setProperties(controller, {test: "value"})', | ||
errors: [{ message: 'Use get/set' }], | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
}, | ||
{ | ||
code: 'import Ember from "ember"; controller.getWithDefault("test", "default")', | ||
filename: 'app/tests/unit/controllers/controller-test.js', | ||
output: 'import Ember from "ember"; Ember.getWithDefault(controller, "test", "default")', | ||
errors: [{ message: 'Use get/set' }], | ||
parserOptions: { ecmaVersion: 6, sourceType: 'module' }, | ||
}, | ||
], | ||
}); |
Sorry, the diff of this file is not supported yet
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
323826
93
5862
170
1