eslint-plugin-conventions 6.0.6 → 6.0.8
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-conventions",
|
|
3
|
-
"version": "6.0.
|
|
3
|
+
"version": "6.0.8",
|
|
4
4
|
"description": "ESLint plugin for team code conventions — enforces filename case, magic-number bans, commented-out code, expiring TODOs, and deprecated-API usage.",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"node": ">=18.0.0"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"@interlace/eslint-devkit": "^1.19.
|
|
53
|
+
"@interlace/eslint-devkit": "^1.19.7"
|
|
54
54
|
},
|
|
55
55
|
"repository": {
|
|
56
56
|
"type": "git",
|
package/src/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.configs=exports.plugin=exports.rules=void 0;const eslint_devkit_1=require("@interlace/eslint-devkit");exports.rules={get"no-commented-code"(){return require("./rules/conventions/no-commented-code").noCommentedCode},get"expiring-todo-comments"(){return require("./rules/conventions/expiring-todo-comments").expiringTodoComments},get"prefer-code-point"(){return require("./rules/conventions/prefer-code-point").preferCodePoint},get"prefer-dom-node-text-content"(){return require("./rules/conventions/prefer-dom-node-text-content").preferDomNodeTextContent},get"no-console-spaces"(){return require("./rules/conventions/no-console-spaces").noConsoleSpaces},get"no-deprecated-api"(){return require("./rules/deprecation/no-deprecated-api").noDeprecatedApi},get"prefer-dependency-version-strategy"(){return require("./rules/conventions/prefer-dependency-version-strategy").preferDependencyVersionStrategy},get"filename-case"(){return require("./rules/conventions/filename-case").filenameCase},get"consistent-existence-index-check"(){return require("./rules/conventions/consistent-existence-index-check").consistentExistenceIndexCheck},get"no-json-schema-tags"(){return require("./rules/conventions/no-json-schema-tags").noJsonSchemaTags},get"require-data-testid"(){return require("./rules/conventions/require-data-testid").requireDataTestId},get"utm-taxonomy"(){return require("./rules/conventions/utm-taxonomy").utmTaxonomy},get"no-raw-cross-property-href"(){return require("./rules/conventions/no-raw-cross-property-href").noRawCrossPropertyHref},get"analytics-event-naming"(){return require("./rules/conventions/analytics-event-naming").analyticsEventNaming},get"no-magic-numbers"(){return require("./rules/conventions/no-magic-numbers").noMagicNumbers}};(0,eslint_devkit_1.withCanonicalDocsUrls)("plugin-conventions",exports.rules);exports.plugin={meta:{name:"eslint-plugin-conventions",version:"6.0.
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.configs=exports.plugin=exports.rules=void 0;const eslint_devkit_1=require("@interlace/eslint-devkit");exports.rules={get"no-commented-code"(){return require("./rules/conventions/no-commented-code").noCommentedCode},get"expiring-todo-comments"(){return require("./rules/conventions/expiring-todo-comments").expiringTodoComments},get"prefer-code-point"(){return require("./rules/conventions/prefer-code-point").preferCodePoint},get"prefer-dom-node-text-content"(){return require("./rules/conventions/prefer-dom-node-text-content").preferDomNodeTextContent},get"no-console-spaces"(){return require("./rules/conventions/no-console-spaces").noConsoleSpaces},get"no-deprecated-api"(){return require("./rules/deprecation/no-deprecated-api").noDeprecatedApi},get"prefer-dependency-version-strategy"(){return require("./rules/conventions/prefer-dependency-version-strategy").preferDependencyVersionStrategy},get"filename-case"(){return require("./rules/conventions/filename-case").filenameCase},get"consistent-existence-index-check"(){return require("./rules/conventions/consistent-existence-index-check").consistentExistenceIndexCheck},get"no-json-schema-tags"(){return require("./rules/conventions/no-json-schema-tags").noJsonSchemaTags},get"require-data-testid"(){return require("./rules/conventions/require-data-testid").requireDataTestId},get"utm-taxonomy"(){return require("./rules/conventions/utm-taxonomy").utmTaxonomy},get"no-raw-cross-property-href"(){return require("./rules/conventions/no-raw-cross-property-href").noRawCrossPropertyHref},get"analytics-event-naming"(){return require("./rules/conventions/analytics-event-naming").analyticsEventNaming},get"no-magic-numbers"(){return require("./rules/conventions/no-magic-numbers").noMagicNumbers}};(0,eslint_devkit_1.withCanonicalDocsUrls)("plugin-conventions",exports.rules);exports.plugin={meta:{name:"eslint-plugin-conventions",version:"6.0.8"},rules:exports.rules};exports.configs={recommended:{plugins:{conventions:exports.plugin},rules:{"conventions/no-commented-code":"warn","conventions/expiring-todo-comments":"warn","conventions/no-deprecated-api":"warn","conventions/utm-taxonomy":"error","conventions/no-raw-cross-property-href":"error","conventions/analytics-event-naming":"error"}}};exports.default=exports.plugin;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.consistentExistenceIndexCheck=void 0;const eslint_devkit_1=require("@interlace/eslint-devkit");const eslint_devkit_2=require("@interlace/eslint-devkit");exports.consistentExistenceIndexCheck=(0,eslint_devkit_1.createRule)({name:"consistent-existence-index-check",meta:{type:"suggestion",docs:{url:"https://github.com/ofri-peretz/eslint/blob/main/packages/eslint-plugin-conventions/docs/rules/consistent-existence-index-check.md",description:"Enforce consistent style for checking object property existence"},fixable:"code",messages:{consistentExistenceCheck:(0,eslint_devkit_2.formatLLMMessage)({icon:eslint_devkit_2.MessageIcons.WARNING,issueName:"Inconsistent Property Check",description:"Use consistent method for property existence checks",severity:"MEDIUM",fix:'Use "{{preferred}}" instead of "{{current}}" for property checks',documentationLink:"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/in"})},schema:[{type:"object",properties:{preferred:{type:"string",enum:["in","hasOwnProperty","Object.hasOwn"],default:"Object.hasOwn"}},additionalProperties:false}]},defaultOptions:[{preferred:"Object.hasOwn"}],create(context){const[options]=context.options;const{preferred="Object.hasOwn"}=options||{};function reportInconsistentCheck(node,currentMethod,object,property,surplusArguments=false){let fix;const crossesPrototypeBoundary=currentMethod==="in"!==(preferred==="in");const crossesDispatchBoundary=currentMethod==="hasOwnProperty"||preferred==="hasOwnProperty";const spliceWouldChangeArity=object.type==="SequenceExpression"||property.type==="SequenceExpression";if(!crossesPrototypeBoundary&&!crossesDispatchBoundary&&!spliceWouldChangeArity&&!surplusArguments&&preferred==="Object.hasOwn"){fix=function(fixer){const objectText=context.sourceCode.getText(object);const propertyText=context.sourceCode.getText(property);return fixer.replaceText(node,`Object.hasOwn(${objectText}, ${propertyText})`)}}context.report({node,messageId:"consistentExistenceCheck",data:{current:currentMethod,preferred},fix})}return{CallExpression(node){if(node.callee.type==="MemberExpression"&&(0,eslint_devkit_1.propertyName)(node.callee)==="hasOwnProperty"&&node.arguments.length>=1&&preferred!=="hasOwnProperty"){reportInconsistentCheck(node,"hasOwnProperty",node.callee.object,node.arguments[0],node.arguments.length>1)}if(node.callee.type==="MemberExpression"&&node.callee.object.type==="MemberExpression"&&node.callee.object.object.type==="MemberExpression"&&node.callee.object.object.object.type==="Identifier"&&node.callee.object.object.object.name==="Object"&&(0,eslint_devkit_1.propertyName)(node.callee.object.object)==="prototype"&&(0,eslint_devkit_1.propertyName)(node.callee.object)==="hasOwnProperty"&&(0,eslint_devkit_1.propertyName)(node.callee)==="call"&&node.arguments.length>=2&&preferred!=="hasOwnProperty"){reportInconsistentCheck(node,"Object.prototype.hasOwnProperty.call",node.arguments[0],node.arguments[1],node.arguments.length>2)}if(node.callee.type==="MemberExpression"&&node.callee.object.type==="Identifier"&&node.callee.object.name==="Object"&&(0,eslint_devkit_1.propertyName)(node.callee)==="hasOwn"&&node.arguments.length>=2&&preferred!=="Object.hasOwn"){reportInconsistentCheck(node,"Object.hasOwn",node.arguments[0],node.arguments[1],node.arguments.length>2)}},BinaryExpression(node){if(node.operator==="in"&&node.left.type!=="PrivateIdentifier"&&preferred!=="in"){reportInconsistentCheck(node,"in",node.right,node.left)}}}}});
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.consistentExistenceIndexCheck=void 0;const eslint_devkit_1=require("@interlace/eslint-devkit");const eslint_devkit_2=require("@interlace/eslint-devkit");exports.consistentExistenceIndexCheck=(0,eslint_devkit_1.createRule)({name:"consistent-existence-index-check",meta:{type:"suggestion",docs:{url:"https://github.com/ofri-peretz/eslint/blob/main/packages/eslint-plugin-conventions/docs/rules/consistent-existence-index-check.md",description:"Enforce consistent style for checking object property existence"},fixable:"code",messages:{consistentExistenceCheck:(0,eslint_devkit_2.formatLLMMessage)({icon:eslint_devkit_2.MessageIcons.WARNING,issueName:"Inconsistent Property Check",description:"Use consistent method for property existence checks",severity:"MEDIUM",fix:'Use "{{preferred}}" instead of "{{current}}" for property checks',documentationLink:"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/in"}),nonEquivalentExistenceCheck:(0,eslint_devkit_2.formatLLMMessage)({icon:eslint_devkit_2.MessageIcons.WARNING,issueName:"Inconsistent Property Check",description:"Use consistent method for property existence checks",severity:"MEDIUM",fix:'Change this site by hand: "{{current}}" and "{{preferred}}" disagree on {{disagreement}}',documentationLink:"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/in"})},schema:[{type:"object",properties:{preferred:{type:"string",enum:["in","hasOwnProperty","Object.hasOwn"],default:"Object.hasOwn"}},additionalProperties:false}]},defaultOptions:[{preferred:"Object.hasOwn"}],create(context){const[options]=context.options;const{preferred="Object.hasOwn"}=options||{};function reportInconsistentCheck(node,currentMethod,object,property,surplusArguments=false){let fix;const crossesPrototypeBoundary=currentMethod==="in"!==(preferred==="in");const crossesDispatchBoundary=currentMethod==="hasOwnProperty"||preferred==="hasOwnProperty";const spliceWouldChangeArity=object.type==="SequenceExpression"||property.type==="SequenceExpression";if(!crossesPrototypeBoundary&&!crossesDispatchBoundary&&!spliceWouldChangeArity&&!surplusArguments&&preferred==="Object.hasOwn"){fix=function(fixer){const objectText=context.sourceCode.getText(object);const propertyText=context.sourceCode.getText(property);return fixer.replaceText(node,`Object.hasOwn(${objectText}, ${propertyText})`)}}const disagreement=crossesPrototypeBoundary?"an inherited key":crossesDispatchBoundary?"method dispatch on the object":spliceWouldChangeArity||surplusArguments?"the argument list":void 0;context.report({node,messageId:disagreement?"nonEquivalentExistenceCheck":"consistentExistenceCheck",data:{current:currentMethod,preferred,...disagreement===void 0?{}:{disagreement}},fix})}return{CallExpression(node){if(node.callee.type==="MemberExpression"&&(0,eslint_devkit_1.propertyName)(node.callee)==="hasOwnProperty"&&node.arguments.length>=1&&preferred!=="hasOwnProperty"){reportInconsistentCheck(node,"hasOwnProperty",node.callee.object,node.arguments[0],node.arguments.length>1)}if(node.callee.type==="MemberExpression"&&node.callee.object.type==="MemberExpression"&&node.callee.object.object.type==="MemberExpression"&&node.callee.object.object.object.type==="Identifier"&&node.callee.object.object.object.name==="Object"&&(0,eslint_devkit_1.propertyName)(node.callee.object.object)==="prototype"&&(0,eslint_devkit_1.propertyName)(node.callee.object)==="hasOwnProperty"&&(0,eslint_devkit_1.propertyName)(node.callee)==="call"&&node.arguments.length>=2&&preferred!=="hasOwnProperty"){reportInconsistentCheck(node,"Object.prototype.hasOwnProperty.call",node.arguments[0],node.arguments[1],node.arguments.length>2)}if(node.callee.type==="MemberExpression"&&node.callee.object.type==="Identifier"&&node.callee.object.name==="Object"&&(0,eslint_devkit_1.propertyName)(node.callee)==="hasOwn"&&node.arguments.length>=2&&preferred!=="Object.hasOwn"){reportInconsistentCheck(node,"Object.hasOwn",node.arguments[0],node.arguments[1],node.arguments.length>2)}},BinaryExpression(node){if(node.operator==="in"&&node.left.type!=="PrivateIdentifier"&&preferred!=="in"){reportInconsistentCheck(node,"in",node.right,node.left)}}}}});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.noCommentedCode=void 0;const eslint_devkit_1=require("@interlace/eslint-devkit");const eslint_devkit_2=require("@interlace/eslint-devkit");function looksLikeCode(comment,isBlockComment){if(isBlockComment&&comment.startsWith("*")){return false}let text=comment;if(isBlockComment){text=text.replace(/^\s*\/\*+/,"").replace(/\*+\/\s*$/,"");text=text.split("\n").map(line=>line.replace(/^\s*\*+\s*/,"")).join("\n")}else{text=text.split("\n").map(line=>line.replace(/^\s*\/\/+\s*/,"")).join("\n")}const lines=text.split("\n").map(line=>line.trim()).filter(line=>line.length>0);if(lines.length===0){return false}const STRUCTURAL_CODE=[/^(const|let|var)\s+[A-Za-z_$][\w$]*(\s*:[^=]+)?\s*=/,/^import\s+[^;]*\bfrom\b/,/^import\s+["']/,/^export\s+(default|const|let|var|function|class|\{|\*)/,/^throw\s+new\s+[A-Za-z_$]/,/^(throw|await|yield)\s+[A-Za-z_$][\w$]*\s*[.([]/,/^return\s+(new|await)\s/,/^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\[\s*['"][^'"]+['"]\s*\])+\s*\(/,/=>/,/===|!==/,/^@[A-Za-z_$][\w$]*\s*\(/,/^<[A-Z][\w$]*[\s/>]/];const codePatterns=[/^(const|let|var|function|class|if|for|while|return|import|export)\s+/,/^[a-zA-Z_$][a-zA-Z0-9_$]*\s*[=:]\s*/,/^[a-zA-Z_$][a-zA-Z0-9_$]*\(/,/^[{}[\]]/];const URL_LINE=/^[a-z][a-z0-9+.-]*:\/\//i;const ENDS_LIKE_CODE=/[;{},()[\]]$|=>$/;let codeLikeLines=0;for(const line of lines){if(/^(TODO|FIXME|HACK|XXX)/i.test(line)){continue}if(URL_LINE.test(line)){continue}if(!STRUCTURAL_CODE.some(pattern=>pattern.test(line))&&!ENDS_LIKE_CODE.test(line)){continue}if(STRUCTURAL_CODE.some(pattern=>pattern.test(line))){codeLikeLines++;continue}for(const pattern of codePatterns){if(pattern.test(line)){codeLikeLines++;break}}}return codeLikeLines>0}function countCommentLines(comment){if(!comment)return 0;const newlineCount=(comment.match(/\n/g)||[]).length;return newlineCount>0?newlineCount+1:1}exports.noCommentedCode=(0,eslint_devkit_2.createRule)({name:"no-commented-code",skipGeneratedFiles:true,meta:{type:"suggestion",docs:{url:"https://github.com/ofri-peretz/eslint/blob/main/packages/eslint-plugin-conventions/docs/rules/no-commented-code.md",description:"Detects commented-out code blocks"},hasSuggestions:true,messages:{commentedCode:(0,eslint_devkit_1.formatLLMMessage)({icon:eslint_devkit_1.MessageIcons.WARNING,issueName:"Commented code",description:"Commented-out code detected ({{lines}} lines)",severity:"LOW",fix:"Remove commented code or use version control for history",documentationLink:"https://rules.sonarsource.com/javascript/RSPEC-125/"}),removeCode:(0,eslint_devkit_1.formatLLMMessage)({icon:eslint_devkit_1.MessageIcons.INFO,issueName:"Remove Code",description:"Remove commented code block",severity:"LOW",fix:"Delete the commented code block",documentationLink:"https://rules.sonarsource.com/javascript/RSPEC-125/"}),useVersionControl:(0,eslint_devkit_1.formatLLMMessage)({icon:eslint_devkit_1.MessageIcons.INFO,issueName:"Use Git",description:"Use version control for code history",severity:"LOW",fix:"Delete commented code and use git history instead",documentationLink:"https://git-scm.com/docs/git-log"})},schema:[{type:"object",properties:{ignoreSingleLine:{type:"boolean",default:false,description:"Ignore single-line comments"},ignoreInTests:{type:"boolean",default:true,description:"Ignore comments in test files"},minLines:{type:"number",default:1,minimum:1,description:"Minimum lines of commented code to trigger"}},additionalProperties:false}]},defaultOptions:[{ignoreSingleLine:false,ignoreInTests:true,minLines:1}],create(context,[options={}]){const{ignoreSingleLine=false,ignoreInTests=true,minLines=1}=options||{};const filename=context.filename;const isTestFile=ignoreInTests&&/\.(test|spec)\.
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.noCommentedCode=void 0;const eslint_devkit_1=require("@interlace/eslint-devkit");const eslint_devkit_2=require("@interlace/eslint-devkit");function looksLikeCode(comment,isBlockComment){if(isBlockComment&&comment.startsWith("*")){return false}let text=comment;if(isBlockComment){text=text.replace(/^\s*\/\*+/,"").replace(/\*+\/\s*$/,"");text=text.split("\n").map(line=>line.replace(/^\s*\*+\s*/,"")).join("\n")}else{text=text.split("\n").map(line=>line.replace(/^\s*\/\/+\s*/,"")).join("\n")}const lines=text.split("\n").map(line=>line.trim()).filter(line=>line.length>0);if(lines.length===0){return false}const STRUCTURAL_CODE=[/^(const|let|var)\s+[A-Za-z_$][\w$]*(\s*:[^=]+)?\s*=/,/^import\s+[^;]*\bfrom\b/,/^import\s+["']/,/^export\s+(default|const|let|var|function|class|\{|\*)/,/^throw\s+new\s+[A-Za-z_$]/,/^(throw|await|yield)\s+[A-Za-z_$][\w$]*\s*[.([]/,/^return\s+(new|await)\s/,/^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\[\s*['"][^'"]+['"]\s*\])+\s*\(/,/=>/,/===|!==/,/^@[A-Za-z_$][\w$]*\s*\(/,/^<[A-Z][\w$]*[\s/>]/];const codePatterns=[/^(const|let|var|function|class|if|for|while|return|import|export)\s+/,/^[a-zA-Z_$][a-zA-Z0-9_$]*\s*[=:]\s*/,/^[a-zA-Z_$][a-zA-Z0-9_$]*\(/,/^[{}[\]]/];const URL_LINE=/^[a-z][a-z0-9+.-]*:\/\//i;const ENDS_LIKE_CODE=/[;{},()[\]]$|=>$/;let codeLikeLines=0;for(const line of lines){if(/^(TODO|FIXME|HACK|XXX)/i.test(line)){continue}if(URL_LINE.test(line)){continue}if(!STRUCTURAL_CODE.some(pattern=>pattern.test(line))&&!ENDS_LIKE_CODE.test(line)){continue}if(STRUCTURAL_CODE.some(pattern=>pattern.test(line))){codeLikeLines++;continue}for(const pattern of codePatterns){if(pattern.test(line)){codeLikeLines++;break}}}return codeLikeLines>0}function countCommentLines(comment){if(!comment)return 0;const newlineCount=(comment.match(/\n/g)||[]).length;return newlineCount>0?newlineCount+1:1}exports.noCommentedCode=(0,eslint_devkit_2.createRule)({name:"no-commented-code",skipGeneratedFiles:true,meta:{type:"suggestion",docs:{url:"https://github.com/ofri-peretz/eslint/blob/main/packages/eslint-plugin-conventions/docs/rules/no-commented-code.md",description:"Detects commented-out code blocks"},hasSuggestions:true,messages:{commentedCode:(0,eslint_devkit_1.formatLLMMessage)({icon:eslint_devkit_1.MessageIcons.WARNING,issueName:"Commented code",description:"Commented-out code detected ({{lines}} lines)",severity:"LOW",fix:"Remove commented code or use version control for history",documentationLink:"https://rules.sonarsource.com/javascript/RSPEC-125/"}),removeCode:(0,eslint_devkit_1.formatLLMMessage)({icon:eslint_devkit_1.MessageIcons.INFO,issueName:"Remove Code",description:"Remove commented code block",severity:"LOW",fix:"Delete the commented code block",documentationLink:"https://rules.sonarsource.com/javascript/RSPEC-125/"}),useVersionControl:(0,eslint_devkit_1.formatLLMMessage)({icon:eslint_devkit_1.MessageIcons.INFO,issueName:"Use Git",description:"Use version control for code history",severity:"LOW",fix:"Delete commented code and use git history instead",documentationLink:"https://git-scm.com/docs/git-log"})},schema:[{type:"object",properties:{ignoreSingleLine:{type:"boolean",default:false,description:"Ignore single-line comments"},ignoreInTests:{type:"boolean",default:true,description:"Ignore comments in test files"},minLines:{type:"number",default:1,minimum:1,description:"Minimum lines of commented code to trigger"}},additionalProperties:false}]},defaultOptions:[{ignoreSingleLine:false,ignoreInTests:true,minLines:1}],create(context,[options={}]){const{ignoreSingleLine=false,ignoreInTests=true,minLines=1}=options||{};const filename=context.filename;const isTestFile=ignoreInTests&&/\.(test|spec)\.[cm]?[jt]sx?$/.test(filename);if(isTestFile){return{}}const sourceCode=context.sourceCode;function checkComment(node){try{const commentText=node.value||"";const isBlockComment=node.type==="Block";const lines=countCommentLines(commentText);if(ignoreSingleLine&&lines===1&&!isBlockComment){return}if(lines<minLines){return}if(looksLikeCode(commentText,isBlockComment)){context.report({node,messageId:"commentedCode",data:{lines:String(lines)},suggest:[{messageId:"removeCode",fix:fixer=>{try{return fixer.remove(node)}catch{return null}}},{messageId:"useVersionControl",fix:()=>null}]})}}catch{return}}function hasCodeBetween(before,after){const nextToken=sourceCode.getTokenAfter(before,{includeComments:false});return nextToken!==null&&nextToken.range[0]<after.range[0]}return{Program(){const comments=sourceCode.getAllComments();const groupedComments=[];let currentGroup=[];for(let i=0;i<comments.length;i++){const comment=comments[i];const commentText=comment.value||"";const isBlockComment=comment.type==="Block";if(looksLikeCode(commentText,isBlockComment)){const previous=currentGroup[currentGroup.length-1];if(previous&&hasCodeBetween(previous,comment)){groupedComments.push([...currentGroup]);currentGroup=[]}currentGroup.push(comment)}else{if(currentGroup.length>0){groupedComments.push([...currentGroup]);currentGroup=[]}}}if(currentGroup.length>0){groupedComments.push(currentGroup)}groupedComments.forEach(group=>{if(group.length===1){checkComment(group[0])}else{const firstComment=group[0];const totalLines=group.reduce((sum,comment)=>{const commentText=comment.value||"";return sum+countCommentLines(commentText)},0);if(totalLines>=minLines){context.report({node:firstComment,messageId:"commentedCode",data:{lines:String(totalLines)},suggest:[{messageId:"removeCode",fix:fixer=>{try{return fixer.removeRange([group[0].range[0],group[group.length-1].range[1]])}catch{return null}}},{messageId:"useVersionControl",fix:()=>null}]})}}})}}}});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.preferDependencyVersionStrategy=void 0;const eslint_devkit_1=require("@interlace/eslint-devkit");const eslint_devkit_2=require("@interlace/eslint-devkit");const
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.preferDependencyVersionStrategy=void 0;const eslint_devkit_1=require("@interlace/eslint-devkit");const eslint_devkit_2=require("@interlace/eslint-devkit");const DEPENDENCY_KEYS=new Set(["dependencies","devDependencies","peerDependencies","optionalDependencies"]);function keyName(prop){const key=prop.key;if(!prop.computed&&(key.type==="Identifier"||key.type==="JSONIdentifier")){return key.name}if((key.type==="Literal"||key.type==="JSONLiteral")&&typeof key.value==="string"){return key.value}return null}exports.preferDependencyVersionStrategy=(0,eslint_devkit_2.createRule)({name:"prefer-dependency-version-strategy",meta:{type:"suggestion",docs:{url:"https://github.com/ofri-peretz/eslint/blob/main/packages/eslint-plugin-conventions/docs/rules/prefer-dependency-version-strategy.md",description:"Enforce consistent version strategy (caret, tilde, exact, etc.) for package.json dependencies"},fixable:"code",messages:{preferStrategy:(0,eslint_devkit_1.formatLLMMessage)({icon:eslint_devkit_1.MessageIcons.PACKAGE,issueName:"Dependency Version Strategy",description:'Dependency "{{name}}" should use {{strategy}} version',severity:"MEDIUM",fix:'Change "{{current}}" to "{{expected}}" for version flexibility',documentationLink:"https://docs.npmjs.com/cli/v10/configuring-npm/package-json#dependencies"}),invalidStrategy:(0,eslint_devkit_1.formatLLMMessage)({icon:eslint_devkit_1.MessageIcons.WARNING,issueName:"Invalid Version Strategy",description:'Strategy "{{strategy}}" is not valid',severity:"MEDIUM",fix:"Use one of: caret (^), tilde (~), exact (no prefix), range (<, >, ||), or any",documentationLink:"https://docs.npmjs.com/cli/v10/configuring-npm/package-json#dependencies"})},schema:[{type:"object",properties:{strategy:{type:"string",enum:["caret","tilde","exact","range","any"],description:"Version strategy to enforce: caret (^), tilde (~), exact (no prefix), range (allows <, >, ||), or any (allows all)"},allowWorkspace:{type:"boolean",description:"Allow workspace: protocol versions",default:true},allowFile:{type:"boolean",description:"Allow file: protocol versions",default:true},allowLink:{type:"boolean",description:"Allow link: protocol versions",default:true},overrides:{type:"object",additionalProperties:{type:"string",enum:["caret","tilde","exact","range","any"]},description:'Package-specific strategy overrides. Key is package name, value is strategy. Example: { "react": "exact", "lodash": "tilde" }'}},additionalProperties:false}]},defaultOptions:[{strategy:"caret",allowWorkspace:true,allowFile:true,allowLink:true,overrides:{}}],create(context){const options=context.options[0]||{};const{strategy="caret",allowWorkspace=true,allowFile=true,allowLink=true,overrides={}}=options;const validStrategies=["caret","tilde","exact","range","any"];if(!validStrategies.includes(strategy)){context.report({loc:{line:1,column:0},messageId:"invalidStrategy",data:{strategy}});return{}}if(strategy==="any"){return{}}function checkVersion(node,depName,version){if(allowWorkspace&&version.startsWith("workspace:"))return;if(allowFile&&version.startsWith("file:"))return;if(allowLink&&version.startsWith("link:"))return;if(!version.match(/^[\^~<>=]?\d+\.\d+\.\d+/))return;const packageStrategy=overrides[depName]||strategy;if(packageStrategy==="any")return;let expectedVersion=version;let needsFix=false;const isRangeSpecifier=version.includes("||")||version.includes(">")||version.includes("<")||version.includes(" - ");if(isRangeSpecifier&&packageStrategy!=="range")return;const baseVersion=version.replace(/^[\^~<>=]+/,"");switch(packageStrategy){case"caret":if(!version.startsWith("^")){expectedVersion=`^${baseVersion}`;needsFix=true}break;case"tilde":if(!version.startsWith("~")){expectedVersion=`~${baseVersion}`;needsFix=true}break;case"exact":{if(version!==baseVersion){expectedVersion=baseVersion;needsFix=true}break}case"range":if(!version.includes("||")&&!version.includes(">=")&&!version.includes("<=")&&!version.includes(">")&&!version.includes("<")&&!version.includes(" - ")){expectedVersion=`^${baseVersion}`;needsFix=true}break}if(needsFix){context.report({node:node.value,messageId:"preferStrategy",data:{name:depName,strategy:packageStrategy,current:version,expected:expectedVersion},fix(fixer){return fixer.replaceText(node.value,JSON.stringify(expectedVersion))}})}}const checkDependencyBlock=node=>{if(!DEPENDENCY_KEYS.has(keyName(node)??""))return;const block=node.value;if(block.type!=="ObjectExpression"&&block.type!=="JSONObjectExpression"){return}for(const prop of block.properties){if(prop.type!=="Property"&&prop.type!=="JSONProperty"){continue}const value=prop.value;if(value.type!=="Literal"&&value.type!=="JSONLiteral")continue;const depName=keyName(prop);if(depName&&typeof value.value==="string"){checkVersion(prop,depName,value.value)}}};return{Property:checkDependencyBlock,JSONProperty:checkDependencyBlock}}});
|