From b25d749fdeaefb921512d511e6cecab8c3e1c756 Mon Sep 17 00:00:00 2001 From: "haifeng.li" Date: Tue, 4 Nov 2025 14:07:46 -0800 Subject: [PATCH 1/7] feat: support static analyzer with version 260.31.0 --- README.md | 21 +- package.json | 186 +++++------ .../rules/artifacts-combined-files/.DS_Store | Bin 0 -> 6148 bytes .../fileUpload/test.js | 13 +- .../rules/artifacts-combined-files/helper.js | 9 +- ...sion-contains-module-level-variable-ref.js | 3 + ...ter-contains-more-than-return-statement.js | 4 +- yarn.lock | 290 ++++++++---------- 8 files changed, 259 insertions(+), 267 deletions(-) create mode 100644 test/lib/rules/artifacts-combined-files/.DS_Store diff --git a/README.md b/README.md index 6d30f96..83ea6e5 100644 --- a/README.md +++ b/README.md @@ -33,13 +33,32 @@ ESLint version-specific configuration examples are provided below. Here are some The default configurations are now in the flat config format supported by ESLint 9 and beyond. Here's how to include the `recommended` config in your flat config: +```javascript +// eslint.config.js +const { defineConfig } = require("eslint/config"); +const lwcGraphAnalyzerPlugin = require("@salesforce/eslint-plugin-lwc-graph-analyzer"); + +module.exports = defineConfig([ + { + plugins: { + "@salesforce/lwc-graph-analyzer": lwcGraphAnalyzerPlugin, + }, + extends: [lwcGraphAnalyzerPlugin.configs.recommended], + }, +]); +``` + ```javascript // eslint.config.mjs import js from '@eslint/js'; import lwcGraphAnalyzerPlugin from '@salesforce/eslint-plugin-lwc-graph-analyzer'; export default [ - { plugins: { '@salesforce/lwc-graph-analyzer': lwcGraphAnalyzerPlugin } }, + { + plugins: { + '@salesforce/lwc-graph-analyzer': lwcGraphAnalyzerPlugin + } + }, js.configs.recommended, lwcGraphAnalyzerPlugin.configs.recommended ]; diff --git a/package.json b/package.json index e2bde22..90af1f1 100644 --- a/package.json +++ b/package.json @@ -1,100 +1,100 @@ { - "name": "@salesforce/eslint-plugin-lwc-graph-analyzer", - "version": "1.0.0", - "description": "ESLint plugin to analyze data graph in a LWC component", - "contributors": [ - { - "name": "Andrew Huffman", - "url": "https://github.com/AndrewHuffman" + "name": "@salesforce/eslint-plugin-lwc-graph-analyzer", + "version": "1.1.0", + "description": "ESLint plugin to analyze data graph in a LWC component", + "contributors": [ + { + "name": "Andrew Huffman", + "url": "https://github.com/AndrewHuffman" + }, + { + "name": "Kevin Hawkins", + "url": "https://github.com/khawkins" + }, + { + "name": "Meisam Seyed Aliroteh", + "url": "https://github.com/maliroteh-sf" + }, + { + "name": "Takashi Arai", + "url": "https://github.com/sfdctaka" + }, + { + "name": "Dustin Breese", + "url": "https://github.com/dbreese" + } + ], + "homepage": "https://github.com/salesforce/eslint-plugin-lwc-graph-analyzer", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/salesforce/eslint-plugin-lwc-graph-analyzer.git" }, - { - "name": "Kevin Hawkins", - "url": "https://github.com/khawkins" + "main": "lib/index.js", + "types": "lib/index.d.ts", + "directories": { + "lib": "lib", + "rules": "lib/rules", + "test": "test" }, - { - "name": "Meisam Seyed Aliroteh", - "url": "https://github.com/maliroteh-sf" + "files": [ + "lib/**/*", + "!**/test/**" + ], + "devDependencies": { + "@eslint/js": "^9.30.1", + "@typescript-eslint/parser": "^8.35.1", + "chai": "^4.5.0", + "eslint": "^9.28.0", + "eslint-plugin-eslint-plugin": "^6.5.0", + "eslint-plugin-n": "^17.20.0", + "husky": "^9.1.7", + "jest": "^29.7.0", + "jest-chain": "^1.1.6", + "jest-extended": "^4.0.2", + "jest-junit": "^16.0.0", + "jest-sonar-reporter": "^2.0.0", + "prettier": "^3.6.2", + "typescript": "^5.8.3", + "typescript-eslint": "^8.35.1" }, - { - "name": "Takashi Arai", - "url": "https://github.com/sfdctaka" + "dependencies": { + "@babel/core": "^7.28.0", + "@babel/eslint-parser": "^7.28.0", + "@komaci/static-analyzer": "^260.31.0", + "@lwc/errors": "^8.21.1", + "@lwc/metadata": "^12.0.0", + "@lwc/sfdc-compiler-utils": "^12.0.0", + "@lwc/template-compiler": "^8.21.1", + "@types/eslint": "^9.6.1" }, - { - "name": "Dustin Breese", - "url": "https://github.com/dbreese" + "scripts": { + "format": "prettier --list-different \"**/*.js\"", + "format:fix": "prettier --write \"**/*.{js,json}\"", + "lint": "eslint", + "test": "yarn jest --coverage", + "prepare": "husky" + }, + "jestSonar": { + "sonar56x": true, + "reportPath": "reports/coverage", + "reportFile": "sonar-report.xml", + "indent": 4 + }, + "prettier": { + "printWidth": 100, + "tabWidth": 4, + "singleQuote": true, + "trailingComma": "none" + }, + "engines": { + "node": ">=20" + }, + "peerDependencies": { + "eslint": ">=7" + }, + "volta": { + "node": "20.18.0", + "yarn": "1.22.22" } - ], - "homepage": "https://github.com/salesforce/eslint-plugin-lwc-graph-analyzer", - "license": "MIT", - "repository": { - "type": "git", - "url": "https://github.com/salesforce/eslint-plugin-lwc-graph-analyzer.git" - }, - "main": "lib/index.js", - "types": "lib/index.d.ts", - "directories": { - "lib": "lib", - "rules": "lib/rules", - "test": "test" - }, - "files": [ - "lib/**/*", - "!**/test/**" - ], - "devDependencies": { - "@eslint/js": "^9.30.1", - "@typescript-eslint/parser": "^8.35.1", - "chai": "^4.5.0", - "eslint": "^9.28.0", - "eslint-plugin-eslint-plugin": "^6.5.0", - "eslint-plugin-n": "^17.20.0", - "husky": "^9.1.7", - "jest": "^29.7.0", - "jest-chain": "^1.1.6", - "jest-extended": "^4.0.2", - "jest-junit": "^16.0.0", - "jest-sonar-reporter": "^2.0.0", - "prettier": "^3.6.2", - "typescript": "^5.8.3", - "typescript-eslint": "^8.35.1" - }, - "dependencies": { - "@babel/core": "^7.28.0", - "@babel/eslint-parser": "^7.28.0", - "@komaci/static-analyzer": "^252.1.0", - "@lwc/errors": "~3.5.0", - "@lwc/metadata": "3.5.0-0", - "@lwc/sfdc-compiler-utils": "3.5.0-0", - "@lwc/template-compiler": "~3.5.0", - "@types/eslint": "^9.6.1" - }, - "scripts": { - "format": "prettier --list-different \"**/*.js\"", - "format:fix": "prettier --write \"**/*.{js,json}\"", - "lint": "eslint", - "test": "yarn jest --coverage", - "prepare": "husky" - }, - "jestSonar": { - "sonar56x": true, - "reportPath": "reports/coverage", - "reportFile": "sonar-report.xml", - "indent": 4 - }, - "prettier": { - "printWidth": 100, - "tabWidth": 4, - "singleQuote": true, - "trailingComma": "none" - }, - "engines": { - "node": ">=20" - }, - "peerDependencies": { - "eslint": ">=7" - }, - "volta": { - "node": "20.18.0", - "yarn": "1.22.22" - } } diff --git a/test/lib/rules/artifacts-combined-files/.DS_Store b/test/lib/rules/artifacts-combined-files/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..c8b2312f18bddaa90e2552295dc899b9ddcdc5b5 GIT binary patch literal 6148 zcmeHKOH0E*5T0$TO)WwW3VI88E!b))6fYsxKVWNC+TW z$Y#f1WPsLg1MVQfb&KK4`i0{`FHB{K@wc#-CWB$U{w@l|(%O32DqB_S#($7we;5o$ z125=bQSVI3G@RK%c#*{8uDx|Evtf{AabFcAQH&|qmq`}Mu_s4aG*Gp^4puuQ{zods=fQ?E|!%hpp+fVr}p3ADwm|)2B?nXhsG8d`dPA&fpb|rIUO1`&lZp zdyLO&XElt>05iZ0tN;UM>$9pWFjt-;Gr$b|i~-so98^NrV6IVZ9oW$Ik>Vvn613?p zLFgEC4dxm#f+BP&qAnHYi6L}3`W=(!8q787au8}{{Eit}m=}srqodzZ=^$K<+%f~q zz&ry*-L>ibKl%RsKVQT>W`G&^R}6?!$M1MJC3CheOpeZ42lW<}gz|EYpCxFhqZo7P dDBeL;f_{e#MAu-h5j`k;5l}R6!wmc?10NqlO`re( literal 0 HcmV?d00001 diff --git a/test/lib/rules/artifacts-combined-files/fileUpload/test.js b/test/lib/rules/artifacts-combined-files/fileUpload/test.js index b1e29ef..836aaad 100644 --- a/test/lib/rules/artifacts-combined-files/fileUpload/test.js +++ b/test/lib/rules/artifacts-combined-files/fileUpload/test.js @@ -27,6 +27,7 @@ export default class FileUpload extends LightningElement { /* eslint-disable */ get fileName() { + // This getter voilates the rule no-getter-contains-more-than-return-statement since it is referenced in the template html const file = this.files && this.files[0]; if (file) { return file.name; @@ -35,7 +36,7 @@ export default class FileUpload extends LightningElement { } /* eslint-enable */ - /* eslint-disable @salesforce/lwc-graph-analyzer/no-getter-contains-more-than-return-statement */ + // No longer voilating the rule no-getter-contains-more-than-return-statement get fileName1() { const file = this.files && this.files[0]; if (file) { @@ -43,9 +44,8 @@ export default class FileUpload extends LightningElement { } return undefined; } - /* eslint-enable @salesforce/lwc-graph-analyzer/no-getter-contains-more-than-return-statement */ - // eslint-disable-next-line + // No longer voilating the rule no-getter-contains-more-than-return-statement get fileName2() { const file = this.files && this.files[0]; if (file) { @@ -54,7 +54,7 @@ export default class FileUpload extends LightningElement { return undefined; } - // eslint-disable-next-line @salesforce/lwc-graph-analyzer/no-getter-contains-more-than-return-statement + // No longer voilating the rule no-getter-contains-more-than-return-statement get fileName3() { const file = this.files && this.files[0]; if (file) { @@ -64,7 +64,8 @@ export default class FileUpload extends LightningElement { } // prettier-ignore - get fileName4() { // eslint-disable-line + // No longer voilating the rule no-getter-contains-more-than-return-statement + get fileName4() { const file = this.files && this.files[0]; if (file) { return file.name; @@ -73,7 +74,7 @@ export default class FileUpload extends LightningElement { } // prettier-ignore - get fileName5() { // eslint-disable-line @salesforce/lwc-graph-analyzer/no-getter-contains-more-than-return-statement + get fileName5() { const file = this.files && this.files[0]; if (file) { return file.name; diff --git a/test/lib/rules/artifacts-combined-files/helper.js b/test/lib/rules/artifacts-combined-files/helper.js index 488cb95..905e6d5 100644 --- a/test/lib/rules/artifacts-combined-files/helper.js +++ b/test/lib/rules/artifacts-combined-files/helper.js @@ -54,7 +54,11 @@ function lintBundle(rulePath, target) { const srcCode = readFileSync(testPath).toString(); const linter = new Linter(); - return linter.verify(srcCode, config, { filename: testPath, filterCodeBlock }); + return linter.verify(srcCode, config, { + filename: testPath, + filterCodeBlock, + reportUnusedDisableDirectives: false + }); } /** @@ -76,7 +80,8 @@ function lintProgrammaticBundle(rulePath, target) { const linter = new Linter(); return linter.verify(srcCode, config, { filename: testPath, - filterCodeBlock + filterCodeBlock, + reportUnusedDisableDirectives: false }); } diff --git a/test/lib/rules/no-expression-contains-module-level-variable-ref.js b/test/lib/rules/no-expression-contains-module-level-variable-ref.js index d7256cd..7283edf 100644 --- a/test/lib/rules/no-expression-contains-module-level-variable-ref.js +++ b/test/lib/rules/no-expression-contains-module-level-variable-ref.js @@ -36,6 +36,9 @@ ruleTester.run( testFunction(val){ return val; } + + @wire(findContacts, { searchKey: '$searchKey' }) + contacts; }`, filename: 'lwc-code.js', errors: [ diff --git a/test/lib/rules/no-getter-contains-more-than-return-statement.js b/test/lib/rules/no-getter-contains-more-than-return-statement.js index 3b08f63..5b82f82 100644 --- a/test/lib/rules/no-getter-contains-more-than-return-statement.js +++ b/test/lib/rules/no-getter-contains-more-than-return-statement.js @@ -36,9 +36,7 @@ ruleTester.run( } @wire(getRecord, { recordId: '$config' }) - record(value) { - console.log(value); - } + record1; @wire(getRecord, { recordId: '$myObjLiteral.prop2' }) record2; diff --git a/yarn.lock b/yarn.lock index 29caeeb..e860086 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15,7 +15,7 @@ "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.22.10", "@babel/code-frame@^7.27.1": +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.25.9", "@babel/code-frame@^7.27.1": version "7.27.1" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.27.1.tgz#200f715e66d52a23b221a9435534a91cc13ad5be" integrity sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg== @@ -59,7 +59,18 @@ eslint-visitor-keys "^2.1.0" semver "^6.3.1" -"@babel/generator@^7.22.10", "@babel/generator@^7.28.0", "@babel/generator@^7.7.2", "@babel/generator@^7.9.0": +"@babel/generator@^7.25.9": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.28.5.tgz#712722d5e50f44d07bc7ac9fe84438742dd61298" + integrity sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ== + dependencies: + "@babel/parser" "^7.28.5" + "@babel/types" "^7.28.5" + "@jridgewell/gen-mapping" "^0.3.12" + "@jridgewell/trace-mapping" "^0.3.28" + jsesc "^3.0.2" + +"@babel/generator@^7.28.0", "@babel/generator@^7.7.2", "@babel/generator@^7.9.0": version "7.28.0" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.28.0.tgz#9cc2f7bd6eb054d77dc66c2664148a0c5118acd2" integrity sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg== @@ -81,31 +92,11 @@ lru-cache "^5.1.1" semver "^6.3.1" -"@babel/helper-environment-visitor@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz#f06dd41b7c1f44e1f8da6c4055b41ab3a09a7e98" - integrity sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q== - -"@babel/helper-function-name@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz#ede300828905bb15e582c037162f99d5183af1be" - integrity sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ== - dependencies: - "@babel/template" "^7.22.5" - "@babel/types" "^7.22.5" - "@babel/helper-globals@^7.28.0": version "7.28.0" resolved "https://registry.yarnpkg.com/@babel/helper-globals/-/helper-globals-7.28.0.tgz#b9430df2aa4e17bc28665eadeae8aa1d985e6674" integrity sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw== -"@babel/helper-hoist-variables@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" - integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== - dependencies: - "@babel/types" "^7.22.5" - "@babel/helper-module-imports@^7.27.1": version "7.27.1" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz#7ef769a323e2655e126673bb6d2d6913bbead204" @@ -128,27 +119,15 @@ resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz#d1b9000752b18d0877cff85a5c376ce5c3121629" integrity sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ== -"@babel/helper-split-export-declaration@^7.22.6": - version "7.22.6" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" - integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-string-parser@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f" - integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw== - -"@babel/helper-string-parser@^7.27.1": +"@babel/helper-string-parser@^7.25.9", "@babel/helper-string-parser@^7.27.1": version "7.27.1" resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz#54da796097ab19ce67ed9f88b47bb2ec49367687" integrity sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA== -"@babel/helper-validator-identifier@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz#9544ef6a33999343c8740fa51350f30eeaaaf193" - integrity sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ== +"@babel/helper-validator-identifier@^7.25.9", "@babel/helper-validator-identifier@^7.28.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz#010b6938fab7cb7df74aa2bbc06aa503b8fe5fb4" + integrity sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q== "@babel/helper-validator-identifier@^7.27.1": version "7.27.1" @@ -168,17 +147,26 @@ "@babel/template" "^7.27.2" "@babel/types" "^7.27.6" -"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.22.10", "@babel/parser@^7.27.2", "@babel/parser@^7.28.0", "@babel/parser@^7.9.0": +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.27.2", "@babel/parser@^7.28.0", "@babel/parser@^7.9.0": version "7.28.0" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.28.0.tgz#979829fbab51a29e13901e5a80713dbcb840825e" integrity sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g== dependencies: "@babel/types" "^7.28.0" -"@babel/parser@~7.22.7": - version "7.22.10" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.10.tgz#e37634f9a12a1716136c44624ef54283cabd3f55" - integrity sha512-lNbdGsQb9ekfsnjFGhEiF4hfFqGgfOP3H3d27re3n+CGhNuTSUEQdfWk556sTLNTloczcdM5TYF2LhzmDQKyvQ== +"@babel/parser@^7.25.9", "@babel/parser@^7.28.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.28.5.tgz#0b0225ee90362f030efd644e8034c99468893b08" + integrity sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ== + dependencies: + "@babel/types" "^7.28.5" + +"@babel/parser@~7.26.2": + version "7.26.10" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.26.10.tgz#e9bdb82f14b97df6569b0b038edd436839c57749" + integrity sha512-6aQR2zGE/QFi8JpDLjUZEPYOs7+mhKXm86VaKFiLP35JQwQb6bwUE+XbvkH0EptsYhbNBSUGaUBLKqxH1xSgsA== + dependencies: + "@babel/types" "^7.26.10" "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" @@ -278,7 +266,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.19.0" -"@babel/template@^7.22.5", "@babel/template@^7.27.2", "@babel/template@^7.3.3": +"@babel/template@^7.25.9", "@babel/template@^7.27.2", "@babel/template@^7.3.3": version "7.27.2" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.27.2.tgz#fa78ceed3c4e7b63ebf6cb39e5852fca45f6809d" integrity sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw== @@ -300,23 +288,20 @@ "@babel/types" "^7.28.0" debug "^4.3.1" -"@babel/traverse@~7.22.8": - version "7.22.10" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.10.tgz#20252acb240e746d27c2e82b4484f199cf8141aa" - integrity sha512-Q/urqV4pRByiNNpb/f5OSv28ZlGJiFiiTh+GAHktbIrkPhPbl90+uW6SmpoLyZqutrg9AEaEf3Q/ZBRHBXgxig== - dependencies: - "@babel/code-frame" "^7.22.10" - "@babel/generator" "^7.22.10" - "@babel/helper-environment-visitor" "^7.22.5" - "@babel/helper-function-name" "^7.22.5" - "@babel/helper-hoist-variables" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/parser" "^7.22.10" - "@babel/types" "^7.22.10" - debug "^4.1.0" +"@babel/traverse@~7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.25.9.tgz#a50f8fe49e7f69f53de5bea7e413cd35c5e13c84" + integrity sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw== + dependencies: + "@babel/code-frame" "^7.25.9" + "@babel/generator" "^7.25.9" + "@babel/parser" "^7.25.9" + "@babel/template" "^7.25.9" + "@babel/types" "^7.25.9" + debug "^4.3.1" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.22.10", "@babel/types@^7.22.5", "@babel/types@^7.27.1", "@babel/types@^7.27.6", "@babel/types@^7.28.0", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.9.0": +"@babel/types@^7.0.0", "@babel/types@^7.27.1", "@babel/types@^7.27.6", "@babel/types@^7.28.0", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.9.0": version "7.28.0" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.28.0.tgz#2fd0159a6dc7353933920c43136335a9b264d950" integrity sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg== @@ -324,14 +309,21 @@ "@babel/helper-string-parser" "^7.27.1" "@babel/helper-validator-identifier" "^7.27.1" -"@babel/types@~7.22.5": - version "7.22.10" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.10.tgz#4a9e76446048f2c66982d1a989dd12b8a2d2dc03" - integrity sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg== +"@babel/types@^7.25.9", "@babel/types@^7.26.10", "@babel/types@^7.28.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.28.5.tgz#10fc405f60897c35f07e85493c932c7b5ca0592b" + integrity sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA== dependencies: - "@babel/helper-string-parser" "^7.22.5" - "@babel/helper-validator-identifier" "^7.22.5" - to-fast-properties "^2.0.0" + "@babel/helper-string-parser" "^7.27.1" + "@babel/helper-validator-identifier" "^7.28.5" + +"@babel/types@~7.26.0": + version "7.26.10" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.26.10.tgz#396382f6335bd4feb65741eacfc808218f859259" + integrity sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ== + dependencies: + "@babel/helper-string-parser" "^7.25.9" + "@babel/helper-validator-identifier" "^7.25.9" "@bcoe/v8-coverage@^0.2.3": version "0.2.3" @@ -724,63 +716,62 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" -"@komaci/common-shared@252.1.0": - version "252.1.0" - resolved "https://registry.yarnpkg.com/@komaci/common-shared/-/common-shared-252.1.0.tgz#55d901a012d799ff52ad2fb7855b022868827dd8" - integrity sha512-1yrQhWooyIOPGdmDubDLQJ7I/pcWtSxCwf9Cdls4TUVrM5IFYfy33w+KH4hEVzQGWfpv3vEEPqH8W+GdzoLUOQ== +"@komaci/common-shared@258.0.0": + version "258.0.0" + resolved "https://registry.yarnpkg.com/@komaci/common-shared/-/common-shared-258.0.0.tgz#996feeaffc7ded5cf283bf1e63f506e032cb086b" + integrity sha512-HOQgPWI9/HPkRzryunFl1/q91Kzs3jwERwfJ0VjkK9ooz9WyAz61RSfsIrfEe6hVRo5xf/4tyMT5gjYgmKfdNA== dependencies: "@babel/core" "^7.9.0" "@babel/generator" "^7.9.0" "@babel/parser" "^7.9.0" "@babel/types" "^7.9.0" -"@komaci/static-analyzer@^252.1.0": - version "252.1.0" - resolved "https://registry.yarnpkg.com/@komaci/static-analyzer/-/static-analyzer-252.1.0.tgz#e45d9301e5912c4a24a983ee515e4deafa04e1f6" - integrity sha512-CfWsBJFT+K8DNGOxi6NxZZAWeZ4PXdFyU5THGzAKlWD0T0mw58eMVgS+U7bV4MRmEAGfygoZnhxYErFjUZA5PQ== +"@komaci/static-analyzer@^260.31.0": + version "260.31.0" + resolved "https://registry.yarnpkg.com/@komaci/static-analyzer/-/static-analyzer-260.31.0.tgz#724fa695bfba49613181e2e7375dddf1955398d1" + integrity sha512-uRAlHR8Nai/3Hr0YKXl4z8DgGqHMerK5mNZ5w9+DBlp15NGK9OkBwGT8SpzR9rKg9nlNVovVk4uWPA2wHdX5ug== dependencies: "@babel/types" "^7.9.0" - "@komaci/common-shared" "252.1.0" - -"@lwc/errors@3.5.0", "@lwc/errors@~3.5.0": - version "3.5.0" - resolved "https://registry.yarnpkg.com/@lwc/errors/-/errors-3.5.0.tgz#4e3dbc008c2ea13707da08851cfb872215ee4b42" - integrity sha512-OQ9/QqZjd4vRfs7s2bGjb20Vjq8KW7Dbce7aBCE1TTlsVpCJBoGWzUJVoI1ts6EkfGlB1lz5REK0SDIKg6IkzA== - -"@lwc/metadata@3.5.0-0": - version "3.5.0-0" - resolved "https://registry.yarnpkg.com/@lwc/metadata/-/metadata-3.5.0-0.tgz#4172b1a455de9531e638b85dd93f6ce649349442" - integrity sha512-wYg2DTLVGWudkbfsHLru/aFr3m2UYou351rP/9UWy1/9vuIMETpJNqOONTLHKE022kYi4n6tm40YhYjiTdaYVg== - dependencies: - "@babel/parser" "~7.22.7" - "@babel/traverse" "~7.22.8" - "@babel/types" "~7.22.5" - postcss "~8.4.25" - postcss-selector-parser "~6.0.13" + "@komaci/common-shared" "258.0.0" + +"@lwc/errors@8.23.0", "@lwc/errors@^8.21.1": + version "8.23.0" + resolved "https://registry.yarnpkg.com/@lwc/errors/-/errors-8.23.0.tgz#7c230010e197062a0eae04a4caa4abe4e7df4af3" + integrity sha512-cqziHl/aDg0pgAIm9HhNz2OrR0t08vML7+FNrqgrnaSwLgYCYp2WPNmvMjD5ZRy/bIBESwA/dCWf9Cs7Vo/ZGw== + +"@lwc/metadata@^12.0.0": + version "12.3.4" + resolved "https://registry.yarnpkg.com/@lwc/metadata/-/metadata-12.3.4.tgz#6157c9c520fee811e078594057427a9736322881" + integrity sha512-90+AW7d+txJYAoa5Be+FR5KtppzVOB4pT9bV1OJatZedz79b0JtP/NJGIxItLJHB8mKwb2bAyuzNibysoaM6AA== + dependencies: + "@babel/parser" "~7.26.2" + "@babel/traverse" "~7.25.9" + "@babel/types" "~7.26.0" + "@lwc/sfdc-compiler-utils" "12.3.4" + postcss "~8.4.49" + postcss-selector-parser "~6.1.2" postcss-value-parser "~4.2.0" -"@lwc/sfdc-compiler-utils@3.5.0-0": - version "3.5.0-0" - resolved "https://registry.yarnpkg.com/@lwc/sfdc-compiler-utils/-/sfdc-compiler-utils-3.5.0-0.tgz#44590a1d1539c52bc92c4bc4a3f2f2637dbc6a0a" - integrity sha512-p7kUpuRPuB5a8iAkK5ph15hQmi7h8b2MPZh4dW53VjpKvX2rdXUuIbIdjuhVitMYpXoBmsVrPVA1umrKJ7etHA== - -"@lwc/shared@3.5.0": - version "3.5.0" - resolved "https://registry.yarnpkg.com/@lwc/shared/-/shared-3.5.0.tgz#3694ebe6c840d060b9dc370a43198f94ac77ab25" - integrity sha512-tbE2sv1woi9q+iiDNPo2qTvMwqs6IwstPfGA1A6bMx9S4l1jVkrerDsPJvYTwaFG2Zc9pUNSX/3ytAXarvuVMg== - -"@lwc/template-compiler@~3.5.0": - version "3.5.0" - resolved "https://registry.yarnpkg.com/@lwc/template-compiler/-/template-compiler-3.5.0.tgz#d026f23c480d541e241f5a91273ee57a4ff64993" - integrity sha512-S62vTDFUyw4NjZGzXiZce7E1Jy4SU7b/pd23Yyzolb5jSvhpzfuzsATpjMROm58+dks0EBtS6Qx0hG5zIy7OKA== - dependencies: - "@lwc/errors" "3.5.0" - "@lwc/shared" "3.5.0" - acorn "~8.10.0" - astring "~1.8.6" - estree-walker "~2.0.2" +"@lwc/sfdc-compiler-utils@12.3.4", "@lwc/sfdc-compiler-utils@^12.0.0": + version "12.3.4" + resolved "https://registry.yarnpkg.com/@lwc/sfdc-compiler-utils/-/sfdc-compiler-utils-12.3.4.tgz#78f7a2ba3b538bb508a4f9f84f97a5252e574e3c" + integrity sha512-AtP9XBzCnrGreJFunohDGD3ZkdT7VTCBs+EncCJPxD2Ej7pRKXX242d5A/TTfi8sp656FuZ6M/jleMNvIyXlKg== + +"@lwc/shared@8.23.0": + version "8.23.0" + resolved "https://registry.yarnpkg.com/@lwc/shared/-/shared-8.23.0.tgz#c9304f7fd8db4256094e5cbf1960dd4f027aa599" + integrity sha512-g6teckOlRJgPkqFJjjrMWoXwEbP3E0PByVIbrxfvv7gN/d8INL+TOA/Deg5ZgRMwuYUGO0Elr5rGcAK5jj/bhA== + +"@lwc/template-compiler@^8.21.1": + version "8.23.0" + resolved "https://registry.yarnpkg.com/@lwc/template-compiler/-/template-compiler-8.23.0.tgz#323ee9d6476b94421b3041ae359b32ec5bfc0d91" + integrity sha512-E24VtNe4Ej307ui8BuQncBzcd6MdzOjXjrhIOQDnGLzNnGL7I3cuGA2wVwTuV8WNrPg7JkgpJghUduEkN3kubw== + dependencies: + "@lwc/errors" "8.23.0" + "@lwc/shared" "8.23.0" + acorn "~8.15.0" + astring "~1.9.0" he "~1.2.0" - parse5 "~6.0.1" "@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1": version "5.1.1-v1" @@ -1035,16 +1026,11 @@ acorn-jsx@^5.3.2: resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== -acorn@^8.15.0: +acorn@^8.15.0, acorn@~8.15.0: version "8.15.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.15.0.tgz#a360898bc415edaac46c8241f6383975b930b816" integrity sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg== -acorn@~8.10.0: - version "8.10.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" - integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== - ajv@^6.12.4: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" @@ -1104,10 +1090,10 @@ assertion-error@^1.1.0: resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== -astring@~1.8.6: - version "1.8.6" - resolved "https://registry.yarnpkg.com/astring/-/astring-1.8.6.tgz#2c9c157cf1739d67561c56ba896e6948f6b93731" - integrity sha512-ISvCdHdlTDlH5IpxQJIex7BWBywFWgjJSVdwst+/iQCoEYnyOaQ95+X1JGshuBjGp6nxKUy1jMgE3zPqN7fQdg== +astring@~1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/astring/-/astring-1.9.0.tgz#cc73e6062a7eb03e7d19c22d8b0b3451fd9bfeef" + integrity sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg== babel-jest@^29.7.0: version "29.7.0" @@ -1593,11 +1579,6 @@ estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== -estree-walker@~2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" - integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== - esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" @@ -2560,10 +2541,10 @@ ms@^2.1.3: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== -nanoid@^3.3.6: - version "3.3.8" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.8.tgz#b1be3030bee36aaff18bacb375e5cce521684baf" - integrity sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w== +nanoid@^3.3.7: + version "3.3.11" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b" + integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w== natural-compare@^1.4.0: version "1.4.0" @@ -2668,11 +2649,6 @@ parse-json@^5.2.0: json-parse-even-better-errors "^2.3.0" lines-and-columns "^1.1.6" -parse5@~6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" - integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== - path-exists@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" @@ -2698,11 +2674,6 @@ pathval@^1.1.1: resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== - picocolors@^1.1.0, picocolors@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" @@ -2730,10 +2701,10 @@ pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" -postcss-selector-parser@~6.0.13: - version "6.0.13" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz#d05d8d76b1e8e173257ef9d60b706a8e5e99bf1b" - integrity sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ== +postcss-selector-parser@~6.1.2: + version "6.1.2" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz#27ecb41fb0e3b6ba7a1ec84fff347f734c7929de" + integrity sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg== dependencies: cssesc "^3.0.0" util-deprecate "^1.0.2" @@ -2743,14 +2714,14 @@ postcss-value-parser@~4.2.0: resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== -postcss@~8.4.25: - version "8.4.31" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.31.tgz#92b451050a9f914da6755af352bdc0192508656d" - integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ== +postcss@~8.4.49: + version "8.4.49" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.49.tgz#4ea479048ab059ab3ae61d082190fabfd994fe19" + integrity sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA== dependencies: - nanoid "^3.3.6" - picocolors "^1.0.0" - source-map-js "^1.0.2" + nanoid "^3.3.7" + picocolors "^1.1.1" + source-map-js "^1.2.1" prelude-ls@^1.2.1: version "1.2.1" @@ -2889,10 +2860,10 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -source-map-js@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" - integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== +source-map-js@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" + integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== source-map-support@0.5.13: version "0.5.13" @@ -2996,11 +2967,6 @@ tmpl@1.0.5: resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== - to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" From 7229a95b90a0f902686ab3820b2e100386244441 Mon Sep 17 00:00:00 2001 From: "haifeng.li" Date: Tue, 4 Nov 2025 14:26:59 -0800 Subject: [PATCH 2/7] fix: remove stray '.DS_Store' file --- .gitignore | 2 ++ .../lib/rules/artifacts-combined-files/.DS_Store | Bin 6148 -> 0 bytes 2 files changed, 2 insertions(+) delete mode 100644 test/lib/rules/artifacts-combined-files/.DS_Store diff --git a/.gitignore b/.gitignore index 1872c54..14a8279 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ /reports test-report.xml junit.xml + +.DS_Store \ No newline at end of file diff --git a/test/lib/rules/artifacts-combined-files/.DS_Store b/test/lib/rules/artifacts-combined-files/.DS_Store deleted file mode 100644 index c8b2312f18bddaa90e2552295dc899b9ddcdc5b5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKOH0E*5T0$TO)WwW3VI88E!b))6fYsxKVWNC+TW z$Y#f1WPsLg1MVQfb&KK4`i0{`FHB{K@wc#-CWB$U{w@l|(%O32DqB_S#($7we;5o$ z125=bQSVI3G@RK%c#*{8uDx|Evtf{AabFcAQH&|qmq`}Mu_s4aG*Gp^4puuQ{zods=fQ?E|!%hpp+fVr}p3ADwm|)2B?nXhsG8d`dPA&fpb|rIUO1`&lZp zdyLO&XElt>05iZ0tN;UM>$9pWFjt-;Gr$b|i~-so98^NrV6IVZ9oW$Ik>Vvn613?p zLFgEC4dxm#f+BP&qAnHYi6L}3`W=(!8q787au8}{{Eit}m=}srqodzZ=^$K<+%f~q zz&ry*-L>ibKl%RsKVQT>W`G&^R}6?!$M1MJC3CheOpeZ42lW<}gz|EYpCxFhqZo7P dDBeL;f_{e#MAu-h5j`k;5l}R6!wmc?10NqlO`re( From 034639c8a46830d827d4f80c8c1e225a89f2c647 Mon Sep 17 00:00:00 2001 From: "haifeng.li" Date: Wed, 5 Nov 2025 19:17:40 -0800 Subject: [PATCH 3/7] feat: support linting the html content dynamicly --- lib/lwc-bundle.js | 9 +- lib/processor.js | 9 +- test/lib/lwc-bundle.js | 6 +- test/lib/processor.js | 11 +- test/lib/rules/programmatic-bundle-lint.js | 213 +++++++++++++++++++++ test/lib/util/bundle-state-manager.js | 10 +- 6 files changed, 236 insertions(+), 22 deletions(-) create mode 100644 test/lib/rules/programmatic-bundle-lint.js diff --git a/lib/lwc-bundle.js b/lib/lwc-bundle.js index 2fc1c5c..ecea8bd 100644 --- a/lib/lwc-bundle.js +++ b/lib/lwc-bundle.js @@ -123,17 +123,16 @@ class LwcBundle { } /** - * Gets a unique key for this bundle based on its primary file + * Gets a unique key for this bundle based on its js file since komaci only supports js files. This key is used as file name for further linting. * * @returns {string} A unique key in the format `_.` */ getBundleKey() { - const primaryFile = this.primaryFile; - if (!primaryFile) { - throw new Error('Cannot generate bundle key: no primary file exists'); + if (!this.#js) { + throw new Error('Cannot generate bundle key: no js file exists'); } - const { name, ext } = parse(primaryFile.filename); + const { name, ext } = parse(this.#js.filename); return `${name}_${this.#primaryFileUuidKey}${ext}`; } diff --git a/lib/processor.js b/lib/processor.js index 1767539..27a902e 100644 --- a/lib/processor.js +++ b/lib/processor.js @@ -124,17 +124,18 @@ class BundleAnalyzer { setLwcBundleCacheEntry(this.#lwcBundle); - // Get the unique key for this bundle, which will be used as the filename for ESLint processing + // Get the unique key for this bundle, which will be used as the filename for ESLint processing. It should always be a js file since komaci only supports js files. const uniqueFilename = this.#lwcBundle.getBundleKey(); // For JavaScript files, we need to return the original text so that ESLint can parse it // and properly handle disable comments. For all other file types (like HTML), we return - // an empty string to prevent ESLint from attempting to parse them, since our rules - // don't need the parsed AST for non-JS files. + // the JS content from the bundle so that rules can run and report violations targeting + // the HTML file. if (fileExtension === '.js') { return [{ text, filename: uniqueFilename }]; } else { - return [{ text: '', filename: uniqueFilename }]; + // Return JS content so ESLint can parse it and rules can run + return [{ text: this.#lwcBundle.js?.content || '', filename: uniqueFilename }]; } }; diff --git a/test/lib/lwc-bundle.js b/test/lib/lwc-bundle.js index d501a62..5a94c8e 100644 --- a/test/lib/lwc-bundle.js +++ b/test/lib/lwc-bundle.js @@ -191,10 +191,10 @@ describe('LwcBundle', () => { expect(key).to.match(/^test_[0-9a-f-]+\.js$/); }); - it('should throw error when no primary file exists', () => { - const bundle = LwcBundle.lwcBundleFromContent('test', 'js content', 'html content'); + it('should throw error when no js file exists', () => { + const bundle = LwcBundle.lwcBundleFromContent('test', undefined, 'html content'); expect(() => bundle.getBundleKey()).to.throw( - 'Cannot generate bundle key: no primary file exists' + 'Cannot generate bundle key: no js file exists' ); }); }); diff --git a/test/lib/processor.js b/test/lib/processor.js index 61c7403..4ef665e 100644 --- a/test/lib/processor.js +++ b/test/lib/processor.js @@ -65,15 +65,14 @@ describe('BundleAnalyzer', () => { expect(result[0].filename).to.equal(bundleAnalyzer.lwcBundle.getBundleKey()); }); - it('should process html file with existing bundle', () => { + it('should throw error when preprocessing html file with existing bundle that has no js file', () => { const htmlContent = ''; bundleAnalyzer.setLwcBundleFromContent('test', undefined, htmlContent); - bundleAnalyzer.lwcBundle.setPrimaryFileByContent(htmlContent); - const result = bundleAnalyzer.preprocess(htmlContent, 'test.html'); - expect(result).to.have.length(1); - expect(result[0].text).to.equal(''); - expect(result[0].filename).to.equal(bundleAnalyzer.lwcBundle.getBundleKey()); + expect(() => bundleAnalyzer.preprocess(htmlContent, 'test.html')).to.throw( + Error, + 'Cannot generate bundle key: no js file exists' + ); }); it('should return empty array when no matching file found in bundle', () => { diff --git a/test/lib/rules/programmatic-bundle-lint.js b/test/lib/rules/programmatic-bundle-lint.js new file mode 100644 index 0000000..182a58c --- /dev/null +++ b/test/lib/rules/programmatic-bundle-lint.js @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2025, salesforce.com, inc. + * All rights reserved. + * SPDX-License-Identifier: MIT + * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT + */ + +const { readFileSync } = require('fs'); +const { join } = require('path'); +const { Linter } = require('eslint'); +const lwcGraphAnalyzer = require('../../../lib/index'); +const bundleAnalyzer = require('../../../lib/processor'); +const baseConfig = require('../../../lib/configs/base'); + +/** + * Test to verify programmatic linting of both HTML and JS content at runtime + * using setLwcBundleFromContent() approach + */ +describe('Programmatic Bundle Linting', () => { + it('should lint both HTML and JS files with runtime content', () => { + // Create JS content with a getter that violates the rule + // The getter has more than just a return statement AND is referenced in the template + const jsContent = ` +import { LightningElement, track } from 'lwc'; + +export default class TestComponent extends LightningElement { + data = []; + + @track + descriptionValue = ''; + + get displayValue() { + const value = this.data[0]; + if (value) { + return value.name; + } + return 'N/A'; + } + + handleDescriptionInputChange(event) { + this.descriptionValue = event.detail.value; + } + +}`; + + // HTML content that references the getter + const htmlContent = ``; + + // 1. Set up the bundle with all content + bundleAnalyzer.setLwcBundleFromContent( + 'testComponent', // component base name + jsContent, // JS content + htmlContent // HTML content + ); + + // 2. Configure ESLint with the rule that has violations in both files + const pluginPrefix = '@salesforce/lwc-graph-analyzer'; + const config = { + ...baseConfig, + plugins: { [pluginPrefix]: lwcGraphAnalyzer }, + rules: { + [`${pluginPrefix}/no-getter-contains-more-than-return-statement`]: 'error', + [`${pluginPrefix}/no-composition-on-unanalyzable-property-non-public`]: 'error' + } + }; + + const linter = new Linter(); + + // 3. Lint JS file + const jsErrors = linter.verify(jsContent, config, { + filename: 'testComponent.js' + }); + + // 4. Set up the bundle with all content again since the bundle is cleared after each lint call + bundleAnalyzer.setLwcBundleFromContent( + 'testComponent', // component base name + jsContent, // JS content + htmlContent // HTML content + ); + + // 5. Lint HTML file + const htmlErrors = linter.verify(htmlContent, config, { + filename: 'testComponent.html' + }); + + // Verify we got violations for the JS file + // The displayValue getter violates the rule because it's referenced in HTML + expect(jsErrors.length).toBeGreaterThan(0); + const jsViolation = jsErrors.find( + (err) => + err.ruleId === + '@salesforce/lwc-graph-analyzer/no-getter-contains-more-than-return-statement' + ); + expect(jsViolation).toBeDefined(); + expect(jsViolation.ruleId).toBe( + '@salesforce/lwc-graph-analyzer/no-getter-contains-more-than-return-statement' + ); + expect(jsViolation.message).toBe('Getters can only contain a return statement.'); + expect(jsViolation.line).toBeGreaterThan(0); + + expect(htmlErrors.length).toBe(1); + const htmlViolation = htmlErrors[0]; + expect(htmlViolation).toBeDefined(); + expect(htmlViolation.ruleId).toBe( + '@salesforce/lwc-graph-analyzer/no-composition-on-unanalyzable-property-non-public' + ); + expect(htmlViolation.message).toBe( + "This child component references an unanalyzable property 'descriptionValue' that’s not a public property." + ); + expect(htmlViolation.line).toBeGreaterThan(0); + }); + + it('should handle multiple HTML templates', () => { + const jsContent = ` +import { LightningElement } from 'lwc'; +export default class MyComponent extends LightningElement { + get value() { + const x = 1; + return x; + } +}`; + + const htmlContent1 = ``; + const htmlContent2 = ``; + + // Set up bundle with multiple HTML templates + bundleAnalyzer.setLwcBundleFromContent( + 'myComponent', + jsContent, + htmlContent1, + htmlContent2 + ); + + const pluginPrefix = '@salesforce/lwc-graph-analyzer'; + const config = { + ...baseConfig, + plugins: { [pluginPrefix]: lwcGraphAnalyzer }, + rules: { + [`${pluginPrefix}/no-getter-contains-more-than-return-statement`]: 'error' + } + }; + + const linter = new Linter(); + + // Lint JS file + const jsErrors = linter.verify(jsContent, config, { + filename: 'myComponent.js' + }); + + // Should have violation because getter is referenced in HTML + expect(jsErrors.length).toBeGreaterThan(0); + const violation = jsErrors.find( + (err) => + err.ruleId === + '@salesforce/lwc-graph-analyzer/no-getter-contains-more-than-return-statement' + ); + expect(violation).toBeDefined(); + }); + + it('should return empty violations when no errors exist', () => { + const jsContent = ` +import { LightningElement } from 'lwc'; +export default class MyComponent extends LightningElement { + value = 'test'; +}`; + + const htmlContent = ``; + + bundleAnalyzer.setLwcBundleFromContent('myComponent', jsContent, htmlContent); + + const pluginPrefix = '@salesforce/lwc-graph-analyzer'; + const config = { + ...baseConfig, + plugins: { [pluginPrefix]: lwcGraphAnalyzer }, + rules: { + [`${pluginPrefix}/no-getter-contains-more-than-return-statement`]: 'error' + } + }; + + const linter = new Linter(); + + const jsErrors = linter.verify(jsContent, config, { + filename: 'myComponent.js' + }); + + const htmlErrors = linter.verify(htmlContent, config, { + filename: 'myComponent.html' + }); + + // No violations expected since we're using a simple property, not a getter + const jsViolations = jsErrors.filter( + (err) => + err.ruleId === + '@salesforce/lwc-graph-analyzer/no-getter-contains-more-than-return-statement' + ); + const htmlViolations = htmlErrors.filter( + (err) => + err.ruleId === + '@salesforce/lwc-graph-analyzer/no-getter-contains-more-than-return-statement' + ); + + expect(jsViolations.length).toBe(0); + expect(htmlViolations.length).toBe(0); + }); +}); diff --git a/test/lib/util/bundle-state-manager.js b/test/lib/util/bundle-state-manager.js index c145f33..b0ddc88 100644 --- a/test/lib/util/bundle-state-manager.js +++ b/test/lib/util/bundle-state-manager.js @@ -27,7 +27,8 @@ describe('BundleStateManager', () => { it('should add a bundle with html file as primary', () => { const htmlContent = ''; - const bundle = LwcBundle.lwcBundleFromContent('test', undefined, htmlContent); + const jsContent = 'export default class Test {}'; + const bundle = LwcBundle.lwcBundleFromContent('test', jsContent, htmlContent); bundle.setPrimaryFileByContent(htmlContent); const key = bundleStateManager.addBundleState(bundle); @@ -35,10 +36,11 @@ describe('BundleStateManager', () => { expect(bundleStateManager.getBundleByKey(bundle.getBundleKey())).to.equal(bundle); }); - it('should return undefined when bundle has no primary file', () => { - const bundle = LwcBundle.lwcBundleFromContent('test', 'js content', 'html content'); + it('should return defined key when bundle has js file', () => { + const jsContent = 'export default class Test {}'; + const bundle = LwcBundle.lwcBundleFromContent('test', jsContent); const key = bundleStateManager.addBundleState(bundle); - expect(key).to.be.undefined; + expect(key).to.not.be.undefined; }); }); From b391b4b25f8ef6f6415d4554de2ca812d04f724c Mon Sep 17 00:00:00 2001 From: "haifeng.li" Date: Wed, 5 Nov 2025 19:18:13 -0800 Subject: [PATCH 4/7] feat: support minimum node 22 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 90af1f1..ff45f52 100644 --- a/package.json +++ b/package.json @@ -88,13 +88,13 @@ "trailingComma": "none" }, "engines": { - "node": ">=20" + "node": ">=22" }, "peerDependencies": { "eslint": ">=7" }, "volta": { - "node": "20.18.0", + "node": "22.21.1", "yarn": "1.22.22" } } From ea388bb7c523c7739a57d39516365ce541c8f231 Mon Sep 17 00:00:00 2001 From: "haifeng.li" Date: Thu, 6 Nov 2025 09:53:37 -0800 Subject: [PATCH 5/7] fix: avoid errors for LwcBundle.getBundleKey --- lib/lwc-bundle.js | 11 ++--- lib/processor.js | 14 +++---- test/lib/lwc-bundle.js | 4 +- test/lib/processor.js | 11 ++--- test/lib/rules/programmatic-bundle-lint.js | 47 ---------------------- test/lib/util/bundle-state-manager.js | 4 +- 6 files changed, 21 insertions(+), 70 deletions(-) diff --git a/lib/lwc-bundle.js b/lib/lwc-bundle.js index ecea8bd..28d4b69 100644 --- a/lib/lwc-bundle.js +++ b/lib/lwc-bundle.js @@ -125,15 +125,16 @@ class LwcBundle { /** * Gets a unique key for this bundle based on its js file since komaci only supports js files. This key is used as file name for further linting. * - * @returns {string} A unique key in the format `_.` + * @returns {string} A unique key in the format `_.js` */ getBundleKey() { - if (!this.#js) { - throw new Error('Cannot generate bundle key: no js file exists'); + const primaryFile = this.primaryFile; + if (!primaryFile) { + throw new Error('Cannot generate bundle key: no primary file exists'); } - const { name, ext } = parse(this.#js.filename); - return `${name}_${this.#primaryFileUuidKey}${ext}`; + const { name } = parse(primaryFile.filename); + return `${name}_${this.#primaryFileUuidKey}.js`; } /** diff --git a/lib/processor.js b/lib/processor.js index 27a902e..39bd425 100644 --- a/lib/processor.js +++ b/lib/processor.js @@ -127,16 +127,12 @@ class BundleAnalyzer { // Get the unique key for this bundle, which will be used as the filename for ESLint processing. It should always be a js file since komaci only supports js files. const uniqueFilename = this.#lwcBundle.getBundleKey(); - // For JavaScript files, we need to return the original text so that ESLint can parse it - // and properly handle disable comments. For all other file types (like HTML), we return - // the JS content from the bundle so that rules can run and report violations targeting + // For JavaScript files, we need to return the JS content from the bundle so that ESLint can parse it + // and properly handle disable comments. For HTML files, we return + // the JS content too so that rules can run and report violations targeting // the HTML file. - if (fileExtension === '.js') { - return [{ text, filename: uniqueFilename }]; - } else { - // Return JS content so ESLint can parse it and rules can run - return [{ text: this.#lwcBundle.js?.content || '', filename: uniqueFilename }]; - } + + return [{ text: this.#lwcBundle.js?.content || '', filename: uniqueFilename }]; }; /** diff --git a/test/lib/lwc-bundle.js b/test/lib/lwc-bundle.js index 5a94c8e..103d3b0 100644 --- a/test/lib/lwc-bundle.js +++ b/test/lib/lwc-bundle.js @@ -191,10 +191,10 @@ describe('LwcBundle', () => { expect(key).to.match(/^test_[0-9a-f-]+\.js$/); }); - it('should throw error when no js file exists', () => { + it('should throw error when no primary file exists', () => { const bundle = LwcBundle.lwcBundleFromContent('test', undefined, 'html content'); expect(() => bundle.getBundleKey()).to.throw( - 'Cannot generate bundle key: no js file exists' + 'Cannot generate bundle key: no primary file exists' ); }); }); diff --git a/test/lib/processor.js b/test/lib/processor.js index 4ef665e..61c7403 100644 --- a/test/lib/processor.js +++ b/test/lib/processor.js @@ -65,14 +65,15 @@ describe('BundleAnalyzer', () => { expect(result[0].filename).to.equal(bundleAnalyzer.lwcBundle.getBundleKey()); }); - it('should throw error when preprocessing html file with existing bundle that has no js file', () => { + it('should process html file with existing bundle', () => { const htmlContent = ''; bundleAnalyzer.setLwcBundleFromContent('test', undefined, htmlContent); + bundleAnalyzer.lwcBundle.setPrimaryFileByContent(htmlContent); - expect(() => bundleAnalyzer.preprocess(htmlContent, 'test.html')).to.throw( - Error, - 'Cannot generate bundle key: no js file exists' - ); + const result = bundleAnalyzer.preprocess(htmlContent, 'test.html'); + expect(result).to.have.length(1); + expect(result[0].text).to.equal(''); + expect(result[0].filename).to.equal(bundleAnalyzer.lwcBundle.getBundleKey()); }); it('should return empty array when no matching file found in bundle', () => { diff --git a/test/lib/rules/programmatic-bundle-lint.js b/test/lib/rules/programmatic-bundle-lint.js index 182a58c..3bf3cd4 100644 --- a/test/lib/rules/programmatic-bundle-lint.js +++ b/test/lib/rules/programmatic-bundle-lint.js @@ -118,53 +118,6 @@ export default class TestComponent extends LightningElement { expect(htmlViolation.line).toBeGreaterThan(0); }); - it('should handle multiple HTML templates', () => { - const jsContent = ` -import { LightningElement } from 'lwc'; -export default class MyComponent extends LightningElement { - get value() { - const x = 1; - return x; - } -}`; - - const htmlContent1 = ``; - const htmlContent2 = ``; - - // Set up bundle with multiple HTML templates - bundleAnalyzer.setLwcBundleFromContent( - 'myComponent', - jsContent, - htmlContent1, - htmlContent2 - ); - - const pluginPrefix = '@salesforce/lwc-graph-analyzer'; - const config = { - ...baseConfig, - plugins: { [pluginPrefix]: lwcGraphAnalyzer }, - rules: { - [`${pluginPrefix}/no-getter-contains-more-than-return-statement`]: 'error' - } - }; - - const linter = new Linter(); - - // Lint JS file - const jsErrors = linter.verify(jsContent, config, { - filename: 'myComponent.js' - }); - - // Should have violation because getter is referenced in HTML - expect(jsErrors.length).toBeGreaterThan(0); - const violation = jsErrors.find( - (err) => - err.ruleId === - '@salesforce/lwc-graph-analyzer/no-getter-contains-more-than-return-statement' - ); - expect(violation).toBeDefined(); - }); - it('should return empty violations when no errors exist', () => { const jsContent = ` import { LightningElement } from 'lwc'; diff --git a/test/lib/util/bundle-state-manager.js b/test/lib/util/bundle-state-manager.js index b0ddc88..fdefabc 100644 --- a/test/lib/util/bundle-state-manager.js +++ b/test/lib/util/bundle-state-manager.js @@ -36,11 +36,11 @@ describe('BundleStateManager', () => { expect(bundleStateManager.getBundleByKey(bundle.getBundleKey())).to.equal(bundle); }); - it('should return defined key when bundle has js file', () => { + it('should return undefined key when bundle has no primary file', () => { const jsContent = 'export default class Test {}'; const bundle = LwcBundle.lwcBundleFromContent('test', jsContent); const key = bundleStateManager.addBundleState(bundle); - expect(key).to.not.be.undefined; + expect(key).to.be.undefined; }); }); From 8596abbd5db8058d6f2ce0a9ef6ab260f268ab25 Mon Sep 17 00:00:00 2001 From: "haifeng.li" Date: Thu, 6 Nov 2025 12:04:52 -0800 Subject: [PATCH 6/7] fix: update CI/CD to 22 above --- .github/workflows/lint.yml | 2 +- .github/workflows/prettier.yml | 2 +- .github/workflows/run-tests.yml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index ec0ff25..4217a4a 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -6,7 +6,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node: [ 20 ] + node: [ 22 ] name: Linting on Ubuntu with Node ${{ matrix.node }} steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/prettier.yml b/.github/workflows/prettier.yml index 4b16cc5..51a2516 100644 --- a/.github/workflows/prettier.yml +++ b/.github/workflows/prettier.yml @@ -6,7 +6,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node: [ 20 ] + node: [ 22 ] name: Prettier on Ubuntu with Node ${{ matrix.node }} steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index f7737e7..eb6178c 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -6,7 +6,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node: [ 20, 22 ] + node: [ 22, 24 ] name: Run tests on Ubuntu with Node ${{ matrix.node }} steps: - uses: actions/checkout@v4 @@ -20,7 +20,7 @@ jobs: runs-on: windows-latest strategy: matrix: - node: [ 20, 22 ] + node: [ 22, 24 ] name: Run tests on Windows with Node ${{ matrix.node }} steps: - uses: actions/checkout@v4 From cb3bc011c2dc6a030afba192e4b2ce0d155bd0fa Mon Sep 17 00:00:00 2001 From: "haifeng.li" Date: Thu, 6 Nov 2025 12:37:06 -0800 Subject: [PATCH 7/7] fix: revert changes for html lint --- lib/lwc-bundle.js | 8 +++---- lib/processor.js | 17 ++++++++------ test/lib/lwc-bundle.js | 2 +- test/lib/rules/programmatic-bundle-lint.js | 26 ---------------------- 4 files changed, 15 insertions(+), 38 deletions(-) diff --git a/lib/lwc-bundle.js b/lib/lwc-bundle.js index 28d4b69..2fc1c5c 100644 --- a/lib/lwc-bundle.js +++ b/lib/lwc-bundle.js @@ -123,9 +123,9 @@ class LwcBundle { } /** - * Gets a unique key for this bundle based on its js file since komaci only supports js files. This key is used as file name for further linting. + * Gets a unique key for this bundle based on its primary file * - * @returns {string} A unique key in the format `_.js` + * @returns {string} A unique key in the format `_.` */ getBundleKey() { const primaryFile = this.primaryFile; @@ -133,8 +133,8 @@ class LwcBundle { throw new Error('Cannot generate bundle key: no primary file exists'); } - const { name } = parse(primaryFile.filename); - return `${name}_${this.#primaryFileUuidKey}.js`; + const { name, ext } = parse(primaryFile.filename); + return `${name}_${this.#primaryFileUuidKey}${ext}`; } /** diff --git a/lib/processor.js b/lib/processor.js index 39bd425..1767539 100644 --- a/lib/processor.js +++ b/lib/processor.js @@ -124,15 +124,18 @@ class BundleAnalyzer { setLwcBundleCacheEntry(this.#lwcBundle); - // Get the unique key for this bundle, which will be used as the filename for ESLint processing. It should always be a js file since komaci only supports js files. + // Get the unique key for this bundle, which will be used as the filename for ESLint processing const uniqueFilename = this.#lwcBundle.getBundleKey(); - // For JavaScript files, we need to return the JS content from the bundle so that ESLint can parse it - // and properly handle disable comments. For HTML files, we return - // the JS content too so that rules can run and report violations targeting - // the HTML file. - - return [{ text: this.#lwcBundle.js?.content || '', filename: uniqueFilename }]; + // For JavaScript files, we need to return the original text so that ESLint can parse it + // and properly handle disable comments. For all other file types (like HTML), we return + // an empty string to prevent ESLint from attempting to parse them, since our rules + // don't need the parsed AST for non-JS files. + if (fileExtension === '.js') { + return [{ text, filename: uniqueFilename }]; + } else { + return [{ text: '', filename: uniqueFilename }]; + } }; /** diff --git a/test/lib/lwc-bundle.js b/test/lib/lwc-bundle.js index 103d3b0..d501a62 100644 --- a/test/lib/lwc-bundle.js +++ b/test/lib/lwc-bundle.js @@ -192,7 +192,7 @@ describe('LwcBundle', () => { }); it('should throw error when no primary file exists', () => { - const bundle = LwcBundle.lwcBundleFromContent('test', undefined, 'html content'); + const bundle = LwcBundle.lwcBundleFromContent('test', 'js content', 'html content'); expect(() => bundle.getBundleKey()).to.throw( 'Cannot generate bundle key: no primary file exists' ); diff --git a/test/lib/rules/programmatic-bundle-lint.js b/test/lib/rules/programmatic-bundle-lint.js index 3bf3cd4..72232eb 100644 --- a/test/lib/rules/programmatic-bundle-lint.js +++ b/test/lib/rules/programmatic-bundle-lint.js @@ -86,11 +86,6 @@ export default class TestComponent extends LightningElement { htmlContent // HTML content ); - // 5. Lint HTML file - const htmlErrors = linter.verify(htmlContent, config, { - filename: 'testComponent.html' - }); - // Verify we got violations for the JS file // The displayValue getter violates the rule because it's referenced in HTML expect(jsErrors.length).toBeGreaterThan(0); @@ -105,17 +100,6 @@ export default class TestComponent extends LightningElement { ); expect(jsViolation.message).toBe('Getters can only contain a return statement.'); expect(jsViolation.line).toBeGreaterThan(0); - - expect(htmlErrors.length).toBe(1); - const htmlViolation = htmlErrors[0]; - expect(htmlViolation).toBeDefined(); - expect(htmlViolation.ruleId).toBe( - '@salesforce/lwc-graph-analyzer/no-composition-on-unanalyzable-property-non-public' - ); - expect(htmlViolation.message).toBe( - "This child component references an unanalyzable property 'descriptionValue' that’s not a public property." - ); - expect(htmlViolation.line).toBeGreaterThan(0); }); it('should return empty violations when no errors exist', () => { @@ -144,23 +128,13 @@ export default class MyComponent extends LightningElement { filename: 'myComponent.js' }); - const htmlErrors = linter.verify(htmlContent, config, { - filename: 'myComponent.html' - }); - // No violations expected since we're using a simple property, not a getter const jsViolations = jsErrors.filter( (err) => err.ruleId === '@salesforce/lwc-graph-analyzer/no-getter-contains-more-than-return-statement' ); - const htmlViolations = htmlErrors.filter( - (err) => - err.ruleId === - '@salesforce/lwc-graph-analyzer/no-getter-contains-more-than-return-statement' - ); expect(jsViolations.length).toBe(0); - expect(htmlViolations.length).toBe(0); }); });