mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-09-03 23:57:01 +02:00
Add custom binding check as plugin
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"extends": ["@excalidraw/eslint-config", "react-app"],
|
"extends": ["@excalidraw/eslint-config", "react-app"],
|
||||||
|
"plugins": ["excalidraw"],
|
||||||
"rules": {
|
"rules": {
|
||||||
"import/order": [
|
"import/order": [
|
||||||
"warn",
|
"warn",
|
||||||
@@ -38,6 +39,7 @@
|
|||||||
{
|
{
|
||||||
"allowReferrer": true
|
"allowReferrer": true
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"excalidraw/no-binding-direct-mod": "error"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -24,6 +24,7 @@
|
|||||||
"dotenv": "16.0.1",
|
"dotenv": "16.0.1",
|
||||||
"eslint-config-prettier": "8.5.0",
|
"eslint-config-prettier": "8.5.0",
|
||||||
"eslint-config-react-app": "7.0.1",
|
"eslint-config-react-app": "7.0.1",
|
||||||
|
"eslint-plugin-eslint": "file:packages/eslint",
|
||||||
"eslint-plugin-import": "2.31.0",
|
"eslint-plugin-import": "2.31.0",
|
||||||
"eslint-plugin-prettier": "3.3.1",
|
"eslint-plugin-prettier": "3.3.1",
|
||||||
"http-server": "14.1.1",
|
"http-server": "14.1.1",
|
||||||
|
5
packages/eslint/index.js
Normal file
5
packages/eslint/index.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
module.exports = {
|
||||||
|
rules: {
|
||||||
|
"no-binding-direct-mod": require("./no-binding-direct-mod"),
|
||||||
|
},
|
||||||
|
};
|
84
packages/eslint/no-binding-direct-mod.js
Normal file
84
packages/eslint/no-binding-direct-mod.js
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
/** @type {import('eslint').Rule.RuleModule} */
|
||||||
|
module.exports = {
|
||||||
|
meta: {
|
||||||
|
type: "problem",
|
||||||
|
docs: {
|
||||||
|
description:
|
||||||
|
"disallow direct mutation of startBinding or endBinding via mutateElement",
|
||||||
|
category: "Best Practices",
|
||||||
|
recommended: false,
|
||||||
|
},
|
||||||
|
fixable: null,
|
||||||
|
schema: [],
|
||||||
|
messages: {
|
||||||
|
noDirectBindingMutation:
|
||||||
|
"Direct mutation of {{ property }} via mutateElement() is not allowed. Use proper binding update functions instead.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
create(context) {
|
||||||
|
return {
|
||||||
|
CallExpression(node) {
|
||||||
|
// Check if this is a call to mutateElement (direct call or method call)
|
||||||
|
let isMutateElementCall = false;
|
||||||
|
|
||||||
|
if (
|
||||||
|
node.callee.type === "Identifier" &&
|
||||||
|
node.callee.name === "mutateElement"
|
||||||
|
) {
|
||||||
|
// Direct call: mutateElement()
|
||||||
|
isMutateElementCall = true;
|
||||||
|
} else if (
|
||||||
|
node.callee.type === "MemberExpression" &&
|
||||||
|
node.callee.property.type === "Identifier" &&
|
||||||
|
node.callee.property.name === "mutateElement"
|
||||||
|
) {
|
||||||
|
// Method call: something.mutateElement() or this.scene.mutateElement()
|
||||||
|
isMutateElementCall = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isMutateElementCall) {
|
||||||
|
// mutateElement can have different argument patterns:
|
||||||
|
// 1. mutateElement(element, updates) - 2 args
|
||||||
|
// 2. mutateElement(element, elementsMap, updates) - 3 args
|
||||||
|
// 3. mutateElement(element, updates, options) - 3 args
|
||||||
|
let updatesArg = null;
|
||||||
|
|
||||||
|
if (node.arguments.length >= 2) {
|
||||||
|
// Try second argument first (most common pattern)
|
||||||
|
const secondArg = node.arguments[1];
|
||||||
|
if (secondArg.type === "ObjectExpression") {
|
||||||
|
updatesArg = secondArg;
|
||||||
|
} else if (node.arguments.length >= 3) {
|
||||||
|
// If second arg is not an object, try third argument
|
||||||
|
const thirdArg = node.arguments[2];
|
||||||
|
if (thirdArg.type === "ObjectExpression") {
|
||||||
|
updatesArg = thirdArg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updatesArg) {
|
||||||
|
// Look for startBinding or endBinding properties
|
||||||
|
for (const property of updatesArg.properties) {
|
||||||
|
if (
|
||||||
|
property.type === "Property" &&
|
||||||
|
property.key.type === "Identifier" &&
|
||||||
|
(property.key.name === "startBinding" ||
|
||||||
|
property.key.name === "endBinding")
|
||||||
|
) {
|
||||||
|
context.report({
|
||||||
|
node: property,
|
||||||
|
messageId: "noDirectBindingMutation",
|
||||||
|
data: {
|
||||||
|
property: property.key.name,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
11
packages/eslint/package.json
Normal file
11
packages/eslint/package.json
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"name": "eslint-plugin-excalidraw",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"lint": "eslint ."
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"eslint": "^7.32.0"
|
||||||
|
}
|
||||||
|
}
|
@@ -5265,6 +5265,9 @@ eslint-module-utils@^2.12.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
debug "^3.2.7"
|
debug "^3.2.7"
|
||||||
|
|
||||||
|
"eslint-plugin-eslint@file:packages/eslint":
|
||||||
|
version "0.1.0"
|
||||||
|
|
||||||
eslint-plugin-flowtype@^8.0.3:
|
eslint-plugin-flowtype@^8.0.3:
|
||||||
version "8.0.3"
|
version "8.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-8.0.3.tgz#e1557e37118f24734aa3122e7536a038d34a4912"
|
resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-8.0.3.tgz#e1557e37118f24734aa3122e7536a038d34a4912"
|
||||||
|
Reference in New Issue
Block a user