eslint-plugin-conventions 6.0.5 → 6.0.6

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.5",
3
+ "version": "6.0.6",
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.5"
53
+ "@interlace/eslint-devkit": "^1.19.6"
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.5"},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
+ "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.6"},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.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)\.(ts|tsx|js|jsx)$/.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}}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)){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
+ "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)\.(ts|tsx|js|jsx)$/.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}]})}}})}}}});