@loxia-labs/loxia-autopilot-one 1.0.1 → 1.0.3

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.
Files changed (120) hide show
  1. package/README.md +44 -54
  2. package/bin/cli.js +1 -115
  3. package/bin/loxia-terminal-v2.js +3 -0
  4. package/bin/loxia-terminal.js +3 -0
  5. package/bin/start-with-terminal.js +3 -0
  6. package/package.json +14 -15
  7. package/scripts/install-scanners.js +1 -235
  8. package/src/analyzers/CSSAnalyzer.js +1 -297
  9. package/src/analyzers/ConfigValidator.js +1 -690
  10. package/src/analyzers/ESLintAnalyzer.js +1 -320
  11. package/src/analyzers/JavaScriptAnalyzer.js +1 -261
  12. package/src/analyzers/PrettierFormatter.js +1 -247
  13. package/src/analyzers/PythonAnalyzer.js +1 -266
  14. package/src/analyzers/SecurityAnalyzer.js +1 -729
  15. package/src/analyzers/TypeScriptAnalyzer.js +1 -247
  16. package/src/analyzers/codeCloneDetector/analyzer.js +1 -344
  17. package/src/analyzers/codeCloneDetector/detector.js +1 -203
  18. package/src/analyzers/codeCloneDetector/index.js +1 -160
  19. package/src/analyzers/codeCloneDetector/parser.js +1 -199
  20. package/src/analyzers/codeCloneDetector/reporter.js +1 -148
  21. package/src/analyzers/codeCloneDetector/scanner.js +1 -59
  22. package/src/core/agentPool.js +1 -1474
  23. package/src/core/agentScheduler.js +1 -2147
  24. package/src/core/contextManager.js +1 -709
  25. package/src/core/messageProcessor.js +1 -732
  26. package/src/core/orchestrator.js +1 -548
  27. package/src/core/stateManager.js +1 -877
  28. package/src/index.js +1 -631
  29. package/src/interfaces/cli.js +1 -549
  30. package/src/interfaces/terminal/__tests__/smoke/advancedFeatures.test.js +1 -0
  31. package/src/interfaces/terminal/__tests__/smoke/agentControl.test.js +1 -0
  32. package/src/interfaces/terminal/__tests__/smoke/agents.test.js +1 -0
  33. package/src/interfaces/terminal/__tests__/smoke/components.test.js +1 -0
  34. package/src/interfaces/terminal/__tests__/smoke/connection.test.js +1 -0
  35. package/src/interfaces/terminal/__tests__/smoke/enhancements.test.js +1 -0
  36. package/src/interfaces/terminal/__tests__/smoke/imports.test.js +1 -0
  37. package/src/interfaces/terminal/__tests__/smoke/messages.test.js +1 -0
  38. package/src/interfaces/terminal/__tests__/smoke/tools.test.js +1 -0
  39. package/src/interfaces/terminal/api/apiClient.js +1 -0
  40. package/src/interfaces/terminal/api/messageRouter.js +1 -0
  41. package/src/interfaces/terminal/api/session.js +1 -0
  42. package/src/interfaces/terminal/api/websocket.js +1 -0
  43. package/src/interfaces/terminal/components/AgentCreator.js +1 -0
  44. package/src/interfaces/terminal/components/AgentEditor.js +1 -0
  45. package/src/interfaces/terminal/components/AgentSwitcher.js +1 -0
  46. package/src/interfaces/terminal/components/ErrorBoundary.js +1 -0
  47. package/src/interfaces/terminal/components/ErrorPanel.js +1 -0
  48. package/src/interfaces/terminal/components/Header.js +1 -0
  49. package/src/interfaces/terminal/components/HelpPanel.js +1 -0
  50. package/src/interfaces/terminal/components/InputBox.js +1 -0
  51. package/src/interfaces/terminal/components/Layout.js +1 -0
  52. package/src/interfaces/terminal/components/LoadingSpinner.js +1 -0
  53. package/src/interfaces/terminal/components/MessageList.js +1 -0
  54. package/src/interfaces/terminal/components/MultilineTextInput.js +1 -0
  55. package/src/interfaces/terminal/components/SearchPanel.js +1 -0
  56. package/src/interfaces/terminal/components/SettingsPanel.js +1 -0
  57. package/src/interfaces/terminal/components/StatusBar.js +1 -0
  58. package/src/interfaces/terminal/components/TextInput.js +1 -0
  59. package/src/interfaces/terminal/config/agentEditorConstants.js +1 -0
  60. package/src/interfaces/terminal/config/constants.js +1 -0
  61. package/src/interfaces/terminal/index.js +1 -0
  62. package/src/interfaces/terminal/state/useAgentControl.js +1 -0
  63. package/src/interfaces/terminal/state/useAgents.js +1 -0
  64. package/src/interfaces/terminal/state/useConnection.js +1 -0
  65. package/src/interfaces/terminal/state/useMessages.js +1 -0
  66. package/src/interfaces/terminal/state/useTools.js +1 -0
  67. package/src/interfaces/terminal/utils/debugLogger.js +1 -0
  68. package/src/interfaces/terminal/utils/settingsStorage.js +1 -0
  69. package/src/interfaces/terminal/utils/theme.js +1 -0
  70. package/src/interfaces/webServer.js +1 -2162
  71. package/src/modules/fileExplorer/controller.js +1 -280
  72. package/src/modules/fileExplorer/index.js +1 -37
  73. package/src/modules/fileExplorer/middleware.js +1 -92
  74. package/src/modules/fileExplorer/routes.js +1 -125
  75. package/src/modules/fileExplorer/types.js +1 -44
  76. package/src/services/aiService.js +1 -1232
  77. package/src/services/apiKeyManager.js +1 -164
  78. package/src/services/benchmarkService.js +1 -366
  79. package/src/services/budgetService.js +1 -539
  80. package/src/services/contextInjectionService.js +1 -247
  81. package/src/services/conversationCompactionService.js +1 -637
  82. package/src/services/errorHandler.js +1 -810
  83. package/src/services/fileAttachmentService.js +1 -544
  84. package/src/services/modelRouterService.js +1 -366
  85. package/src/services/modelsService.js +1 -322
  86. package/src/services/qualityInspector.js +1 -796
  87. package/src/services/tokenCountingService.js +1 -536
  88. package/src/tools/agentCommunicationTool.js +1 -1344
  89. package/src/tools/agentDelayTool.js +1 -485
  90. package/src/tools/asyncToolManager.js +1 -604
  91. package/src/tools/baseTool.js +1 -800
  92. package/src/tools/browserTool.js +1 -920
  93. package/src/tools/cloneDetectionTool.js +1 -621
  94. package/src/tools/dependencyResolverTool.js +1 -1215
  95. package/src/tools/fileContentReplaceTool.js +1 -875
  96. package/src/tools/fileSystemTool.js +1 -1107
  97. package/src/tools/fileTreeTool.js +1 -853
  98. package/src/tools/imageTool.js +1 -901
  99. package/src/tools/importAnalyzerTool.js +1 -1060
  100. package/src/tools/jobDoneTool.js +1 -248
  101. package/src/tools/seekTool.js +1 -956
  102. package/src/tools/staticAnalysisTool.js +1 -1778
  103. package/src/tools/taskManagerTool.js +1 -2873
  104. package/src/tools/terminalTool.js +1 -2304
  105. package/src/tools/webTool.js +1 -1430
  106. package/src/types/agent.js +1 -519
  107. package/src/types/contextReference.js +1 -972
  108. package/src/types/conversation.js +1 -730
  109. package/src/types/toolCommand.js +1 -747
  110. package/src/utilities/attachmentValidator.js +1 -292
  111. package/src/utilities/configManager.js +1 -582
  112. package/src/utilities/constants.js +1 -722
  113. package/src/utilities/directoryAccessManager.js +1 -535
  114. package/src/utilities/fileProcessor.js +1 -307
  115. package/src/utilities/logger.js +1 -436
  116. package/src/utilities/tagParser.js +1 -1246
  117. package/src/utilities/toolConstants.js +1 -317
  118. package/web-ui/build/index.html +2 -2
  119. package/web-ui/build/static/{index-Dy2bYbOa.css → index-CClD1090.css} +1 -1
  120. package/web-ui/build/static/{index-CjkkcnFA.js → index-lCBai6dX.js} +66 -67
@@ -1,236 +1,2 @@
1
1
  #!/usr/bin/env node
2
- /**
3
- * Post-install script to set up security scanners
4
- * Automatically installs required scanners for the platform
5
- */
6
-
7
- import { exec } from 'child_process';
8
- import { promisify } from 'util';
9
- import https from 'https';
10
- import http from 'http';
11
- import fs from 'fs';
12
- import path from 'path';
13
- import { fileURLToPath } from 'url';
14
- import { createWriteStream } from 'fs';
15
- import { pipeline } from 'stream/promises';
16
-
17
- const execAsync = promisify(exec);
18
- const __filename = fileURLToPath(import.meta.url);
19
- const __dirname = path.dirname(__filename);
20
-
21
- const SCANNER_DIR = path.join(__dirname, '..', 'node_modules', '.scanners');
22
- const SEMGREP_VERSION = 'v1.55.0';
23
-
24
- console.log('═══════════════════════════════════════════════════════════');
25
- console.log(' Installing Security Scanners');
26
- console.log('═══════════════════════════════════════════════════════════\n');
27
-
28
- /**
29
- * Main installation function
30
- */
31
- async function installScanners() {
32
- // Ensure scanner directory exists
33
- await fs.promises.mkdir(SCANNER_DIR, { recursive: true });
34
-
35
- // 1. Check ESLint Security Plugin (should be in package.json)
36
- await checkESLintSecurity();
37
-
38
- // 2. Install Semgrep standalone binary
39
- await installSemgrep();
40
-
41
- // 3. Optionally install Python scanners if Python is available
42
- await installPythonScanners();
43
-
44
- console.log('\n═══════════════════════════════════════════════════════════');
45
- console.log(' Installation Complete');
46
- console.log('═══════════════════════════════════════════════════════════\n');
47
- }
48
-
49
- /**
50
- * Check if ESLint Security Plugin is installed
51
- */
52
- async function checkESLintSecurity() {
53
- console.log('📦 Checking ESLint Security Plugin...');
54
- try {
55
- await import('eslint-plugin-security');
56
- console.log(' ✅ eslint-plugin-security is installed\n');
57
- } catch (error) {
58
- console.log(' ⚠️ eslint-plugin-security not found');
59
- console.log(' Run: npm install --save-dev eslint-plugin-security\n');
60
- }
61
- }
62
-
63
- /**
64
- * Install Semgrep standalone binary for the current platform
65
- */
66
- async function installSemgrep() {
67
- console.log('🔍 Installing Semgrep...');
68
-
69
- const platform = process.platform;
70
- const arch = process.arch;
71
-
72
- // Check if semgrep is already installed globally
73
- try {
74
- const result = await execAsync('semgrep --version', { timeout: 5000 });
75
- console.log(` ✅ Semgrep already installed: ${result.stdout.trim()}`);
76
- console.log(' Using system-installed Semgrep\n');
77
- return;
78
- } catch (error) {
79
- console.log(' Semgrep not found in PATH, installing standalone binary...');
80
- }
81
-
82
- // Determine download URL based on platform
83
- const binaryInfo = getSemgrepBinaryInfo(platform, arch);
84
-
85
- if (!binaryInfo) {
86
- console.log(` ⚠️ No Semgrep binary available for ${platform}-${arch}`);
87
- console.log(' Please install manually: https://semgrep.dev/docs/getting-started/\n');
88
- return;
89
- }
90
-
91
- try {
92
- const binaryPath = path.join(SCANNER_DIR, 'semgrep');
93
-
94
- console.log(` Downloading from ${binaryInfo.url}...`);
95
- await downloadFile(binaryInfo.url, binaryPath);
96
-
97
- // Make executable
98
- await fs.promises.chmod(binaryPath, 0o755);
99
-
100
- console.log(' ✅ Semgrep installed successfully');
101
- console.log(` Location: ${binaryPath}\n`);
102
-
103
- // Add to PATH environment note
104
- console.log(' Note: To use system-wide, add to PATH or install globally:');
105
- console.log(' pip install semgrep\n');
106
- } catch (error) {
107
- console.log(` ⚠️ Failed to install Semgrep: ${error.message}`);
108
- console.log(' You can install manually: pip install semgrep\n');
109
- }
110
- }
111
-
112
- /**
113
- * Get Semgrep binary info for platform
114
- */
115
- function getSemgrepBinaryInfo(platform, arch) {
116
- // Semgrep binary URLs (using latest stable release)
117
- // Note: Semgrep doesn't provide standalone binaries anymore for all platforms
118
- // They recommend using pip install or Docker
119
-
120
- // For now, we'll provide instructions rather than downloading
121
- // The actual implementation would use Semgrep's Python package
122
-
123
- return null; // Will trigger manual installation message
124
- }
125
-
126
- /**
127
- * Install Python-based scanners (Bandit, pip-audit) if Python is available
128
- */
129
- async function installPythonScanners() {
130
- console.log('🐍 Checking Python scanners...');
131
-
132
- // Check if Python is available
133
- let pythonCommand = null;
134
-
135
- try {
136
- await execAsync('python3 --version', { timeout: 5000 });
137
- pythonCommand = 'python3';
138
- } catch (error) {
139
- try {
140
- await execAsync('python --version', { timeout: 5000 });
141
- pythonCommand = 'python';
142
- } catch (error2) {
143
- console.log(' ⚠️ Python not found - skipping Python scanners');
144
- console.log(' To enable Python scanning, install Python and run:');
145
- console.log(' pip install semgrep bandit pip-audit checkov yamllint\n');
146
- return;
147
- }
148
- }
149
-
150
- console.log(` ✅ Python found: ${pythonCommand}`);
151
-
152
- // Security scanners
153
- await installViaPip('semgrep', pythonCommand);
154
- await installViaPip('bandit', pythonCommand);
155
- await installViaPip('pip-audit', pythonCommand);
156
-
157
- // Config validation tools
158
- await installViaPip('checkov', pythonCommand);
159
- await installViaPip('yamllint', pythonCommand);
160
-
161
- console.log('');
162
- }
163
-
164
- /**
165
- * Install a Python package via pip
166
- */
167
- async function installViaPip(packageName, pythonCommand) {
168
- try {
169
- // Check if already installed
170
- const checkResult = await execAsync(`${pythonCommand} -m pip show ${packageName}`, {
171
- timeout: 5000
172
- });
173
- console.log(` ✅ ${packageName} already installed`);
174
- return true;
175
- } catch (error) {
176
- // Not installed, try to install
177
- console.log(` Installing ${packageName}...`);
178
- try {
179
- await execAsync(`${pythonCommand} -m pip install --user ${packageName}`, {
180
- timeout: 60000
181
- });
182
- console.log(` ✅ ${packageName} installed successfully`);
183
- return true;
184
- } catch (installError) {
185
- console.log(` ⚠️ Failed to install ${packageName}: ${installError.message}`);
186
- console.log(` You can install manually: pip install ${packageName}`);
187
- return false;
188
- }
189
- }
190
- }
191
-
192
- /**
193
- * Download a file from URL
194
- */
195
- async function downloadFile(url, outputPath) {
196
- return new Promise((resolve, reject) => {
197
- const client = url.startsWith('https') ? https : http;
198
-
199
- client.get(url, (response) => {
200
- if (response.statusCode === 302 || response.statusCode === 301) {
201
- // Follow redirect
202
- downloadFile(response.headers.location, outputPath)
203
- .then(resolve)
204
- .catch(reject);
205
- return;
206
- }
207
-
208
- if (response.statusCode !== 200) {
209
- reject(new Error(`Failed to download: HTTP ${response.statusCode}`));
210
- return;
211
- }
212
-
213
- const fileStream = createWriteStream(outputPath);
214
- response.pipe(fileStream);
215
-
216
- fileStream.on('finish', () => {
217
- fileStream.close();
218
- resolve();
219
- });
220
-
221
- fileStream.on('error', (error) => {
222
- fs.unlink(outputPath, () => {}); // Delete partial file
223
- reject(error);
224
- });
225
- }).on('error', reject);
226
- });
227
- }
228
-
229
- // Run installation
230
- installScanners().catch((error) => {
231
- console.error('❌ Installation failed:', error.message);
232
- console.error('\nYou can manually install scanners:');
233
- console.error(' npm install --save-dev eslint-plugin-security');
234
- console.error(' pip install semgrep bandit pip-audit');
235
- process.exit(0); // Don't fail npm install
236
- });
2
+ const a0_0xd91e0e=a0_0x3f52;(function(_0x4f74d1,_0x37b7eb){const _0x170bae=a0_0x3f52,_0x3478cb=_0x4f74d1();while(!![]){try{const _0x19876d=-parseInt(_0x170bae(0x197))/0x1*(-parseInt(_0x170bae(0x17a))/0x2)+-parseInt(_0x170bae(0x1b8))/0x3+-parseInt(_0x170bae(0x1a8))/0x4*(-parseInt(_0x170bae(0x19a))/0x5)+-parseInt(_0x170bae(0x18c))/0x6+parseInt(_0x170bae(0x194))/0x7+parseInt(_0x170bae(0x190))/0x8+parseInt(_0x170bae(0x17d))/0x9*(parseInt(_0x170bae(0x181))/0xa);if(_0x19876d===_0x37b7eb)break;else _0x3478cb['push'](_0x3478cb['shift']());}catch(_0x13b3a5){_0x3478cb['push'](_0x3478cb['shift']());}}}(a0_0x5542,0x98991));import{exec}from'child_process';import{promisify}from'util';import a0_0x1da570 from'https';import a0_0x36e13f from'http';import a0_0x3f26ce from'fs';import a0_0x4226c8 from'path';import{fileURLToPath}from'url';import{createWriteStream}from'fs';import{pipeline}from'stream/promises';const execAsync=promisify(exec),__filename=fileURLToPath(import.meta.url),__dirname=a0_0x4226c8[a0_0xd91e0e(0x18e)](__filename),SCANNER_DIR=a0_0x4226c8[a0_0xd91e0e(0x1b2)](__dirname,'..',a0_0xd91e0e(0x195),a0_0xd91e0e(0x18a)),SEMGREP_VERSION=a0_0xd91e0e(0x1b1);function a0_0x3f52(_0xc2c20b,_0x5ed607){_0xc2c20b=_0xc2c20b-0x179;const _0x55422c=a0_0x5542();let _0x3f5223=_0x55422c[_0xc2c20b];return _0x3f5223;}console[a0_0xd91e0e(0x1af)](a0_0xd91e0e(0x17b)),console[a0_0xd91e0e(0x1af)]('\x20\x20Installing\x20Security\x20Scanners'),console[a0_0xd91e0e(0x1af)](a0_0xd91e0e(0x188));async function installScanners(){const _0x288d12=a0_0xd91e0e;await a0_0x3f26ce[_0x288d12(0x1a7)]['mkdir'](SCANNER_DIR,{'recursive':!![]}),await checkESLintSecurity(),await installSemgrep(),await installPythonScanners(),console['log']('\x0a═══════════════════════════════════════════════════════════'),console[_0x288d12(0x1af)](_0x288d12(0x1c0)),console[_0x288d12(0x1af)](_0x288d12(0x188));}async function checkESLintSecurity(){const _0xb6beb9=a0_0xd91e0e;console[_0xb6beb9(0x1af)](_0xb6beb9(0x17c));try{await import(_0xb6beb9(0x18f)),console[_0xb6beb9(0x1af)]('\x20\x20\x20✅\x20eslint-plugin-security\x20is\x20installed\x0a');}catch(_0x1c5980){console[_0xb6beb9(0x1af)](_0xb6beb9(0x1a5)),console[_0xb6beb9(0x1af)]('\x20\x20\x20Run:\x20npm\x20install\x20--save-dev\x20eslint-plugin-security\x0a');}}async function installSemgrep(){const _0x4abc82=a0_0xd91e0e;console[_0x4abc82(0x1af)](_0x4abc82(0x196));const _0x287f95=process[_0x4abc82(0x19f)],_0x38c66c=process['arch'];try{const _0x43ceb7=await execAsync(_0x4abc82(0x180),{'timeout':0x1388});console['log'](_0x4abc82(0x1a0)+_0x43ceb7['stdout']['trim']()),console['log'](_0x4abc82(0x1ae));return;}catch(_0xa9a255){console[_0x4abc82(0x1af)](_0x4abc82(0x19d));}const _0x440350=getSemgrepBinaryInfo(_0x287f95,_0x38c66c);if(!_0x440350){console[_0x4abc82(0x1af)](_0x4abc82(0x1ab)+_0x287f95+'-'+_0x38c66c),console[_0x4abc82(0x1af)](_0x4abc82(0x1b3));return;}try{const _0x5625ce=a0_0x4226c8['join'](SCANNER_DIR,_0x4abc82(0x184));console[_0x4abc82(0x1af)](_0x4abc82(0x1c1)+_0x440350['url']+_0x4abc82(0x186)),await downloadFile(_0x440350[_0x4abc82(0x1b4)],_0x5625ce),await a0_0x3f26ce[_0x4abc82(0x1a7)][_0x4abc82(0x1a4)](_0x5625ce,0x1ed),console[_0x4abc82(0x1af)]('\x20\x20\x20✅\x20Semgrep\x20installed\x20successfully'),console[_0x4abc82(0x1af)](_0x4abc82(0x1b9)+_0x5625ce+'\x0a'),console['log']('\x20\x20\x20Note:\x20To\x20use\x20system-wide,\x20add\x20to\x20PATH\x20or\x20install\x20globally:'),console[_0x4abc82(0x1af)](_0x4abc82(0x187));}catch(_0x351e1c){console[_0x4abc82(0x1af)](_0x4abc82(0x1b0)+_0x351e1c[_0x4abc82(0x1b5)]),console[_0x4abc82(0x1af)](_0x4abc82(0x1bd));}}function getSemgrepBinaryInfo(_0x1384b2,_0x5789c2){return null;}function a0_0x5542(){const _0x43eeb2=['\x0aYou\x20can\x20manually\x20install\x20scanners:','location','895QCAkjx','\x20\x20\x20You\x20can\x20install\x20manually:\x20pip\x20install\x20','error','\x20\x20\x20Semgrep\x20not\x20found\x20in\x20PATH,\x20installing\x20standalone\x20binary...','\x20\x20\x20To\x20enable\x20Python\x20scanning,\x20install\x20Python\x20and\x20run:','platform','\x20\x20\x20✅\x20Semgrep\x20already\x20installed:\x20','python3','get','pipe','chmod','\x20\x20\x20⚠️\x20\x20eslint-plugin-security\x20not\x20found','\x20installed\x20successfully','promises','11492NFtUdT','Failed\x20to\x20download:\x20HTTP\x20','https','\x20\x20\x20⚠️\x20\x20No\x20Semgrep\x20binary\x20available\x20for\x20','headers','close','\x20\x20\x20Using\x20system-installed\x20Semgrep\x0a','log','\x20\x20\x20⚠️\x20\x20Failed\x20to\x20install\x20Semgrep:\x20','v1.55.0','join','\x20\x20\x20Please\x20install\x20manually:\x20https://semgrep.dev/docs/getting-started/\x0a','url','message','pip-audit','statusCode','1676073QxhuQH','\x20\x20\x20Location:\x20','🐍\x20Checking\x20Python\x20scanners...','❌\x20Installation\x20failed:','catch','\x20\x20\x20You\x20can\x20install\x20manually:\x20pip\x20install\x20semgrep\x0a','python\x20--version','\x20-m\x20pip\x20show\x20','\x20\x20Installation\x20Complete','\x20\x20\x20Downloading\x20from\x20','exit','2lVNxlb','═══════════════════════════════════════════════════════════','📦\x20Checking\x20ESLint\x20Security\x20Plugin...','403659tJXvLH','\x20-m\x20pip\x20install\x20--user\x20','\x20already\x20installed','semgrep\x20--version','10ZiTVdm','\x20\x20npm\x20install\x20--save-dev\x20eslint-plugin-security','python','semgrep','\x20\x20\x20✅\x20Python\x20found:\x20','...','\x20\x20\x20pip\x20install\x20semgrep\x0a','═══════════════════════════════════════════════════════════\x0a','\x20\x20\x20⚠️\x20\x20Failed\x20to\x20install\x20','.scanners','checkov','6972486QxWmEX','then','dirname','eslint-plugin-security','2818552TpduYQ','startsWith','\x20\x20\x20Installing\x20','\x20\x20\x20✅\x20','1703793VQkKgJ','node_modules','🔍\x20Installing\x20Semgrep...','1190977RYauCp'];a0_0x5542=function(){return _0x43eeb2;};return a0_0x5542();}async function installPythonScanners(){const _0x12c29a=a0_0xd91e0e;console[_0x12c29a(0x1af)](_0x12c29a(0x1ba));let _0x5bc52d=null;try{await execAsync('python3\x20--version',{'timeout':0x1388}),_0x5bc52d=_0x12c29a(0x1a1);}catch(_0x2532f6){try{await execAsync(_0x12c29a(0x1be),{'timeout':0x1388}),_0x5bc52d=_0x12c29a(0x183);}catch(_0x4f8d2d){console[_0x12c29a(0x1af)]('\x20\x20\x20⚠️\x20\x20Python\x20not\x20found\x20-\x20skipping\x20Python\x20scanners'),console[_0x12c29a(0x1af)](_0x12c29a(0x19e)),console[_0x12c29a(0x1af)]('\x20\x20\x20pip\x20install\x20semgrep\x20bandit\x20pip-audit\x20checkov\x20yamllint\x0a');return;}}console['log'](_0x12c29a(0x185)+_0x5bc52d),await installViaPip(_0x12c29a(0x184),_0x5bc52d),await installViaPip('bandit',_0x5bc52d),await installViaPip(_0x12c29a(0x1b6),_0x5bc52d),await installViaPip(_0x12c29a(0x18b),_0x5bc52d),await installViaPip('yamllint',_0x5bc52d),console[_0x12c29a(0x1af)]('');}async function installViaPip(_0x3a7825,_0x4a99bb){const _0x5237f3=a0_0xd91e0e;try{const _0xbc4779=await execAsync(_0x4a99bb+_0x5237f3(0x1bf)+_0x3a7825,{'timeout':0x1388});return console['log'](_0x5237f3(0x193)+_0x3a7825+_0x5237f3(0x17f)),!![];}catch(_0x547c1e){console[_0x5237f3(0x1af)](_0x5237f3(0x192)+_0x3a7825+_0x5237f3(0x186));try{return await execAsync(_0x4a99bb+_0x5237f3(0x17e)+_0x3a7825,{'timeout':0xea60}),console['log'](_0x5237f3(0x193)+_0x3a7825+_0x5237f3(0x1a6)),!![];}catch(_0x363d58){return console['log'](_0x5237f3(0x189)+_0x3a7825+':\x20'+_0x363d58[_0x5237f3(0x1b5)]),console[_0x5237f3(0x1af)](_0x5237f3(0x19b)+_0x3a7825),![];}}}async function downloadFile(_0x37a548,_0x53b753){return new Promise((_0x4d8a1c,_0x1a7776)=>{const _0x4efcc5=a0_0x3f52,_0x44d5da=_0x37a548[_0x4efcc5(0x191)](_0x4efcc5(0x1aa))?a0_0x1da570:a0_0x36e13f;_0x44d5da[_0x4efcc5(0x1a2)](_0x37a548,_0x32f2ec=>{const _0x5dfbe8=_0x4efcc5;if(_0x32f2ec[_0x5dfbe8(0x1b7)]===0x12e||_0x32f2ec[_0x5dfbe8(0x1b7)]===0x12d){downloadFile(_0x32f2ec[_0x5dfbe8(0x1ac)][_0x5dfbe8(0x199)],_0x53b753)[_0x5dfbe8(0x18d)](_0x4d8a1c)[_0x5dfbe8(0x1bc)](_0x1a7776);return;}if(_0x32f2ec[_0x5dfbe8(0x1b7)]!==0xc8){_0x1a7776(new Error(_0x5dfbe8(0x1a9)+_0x32f2ec['statusCode']));return;}const _0x1eda56=createWriteStream(_0x53b753);_0x32f2ec[_0x5dfbe8(0x1a3)](_0x1eda56),_0x1eda56['on']('finish',()=>{const _0x5e7716=_0x5dfbe8;_0x1eda56[_0x5e7716(0x1ad)](),_0x4d8a1c();}),_0x1eda56['on'](_0x5dfbe8(0x19c),_0x2ad452=>{a0_0x3f26ce['unlink'](_0x53b753,()=>{}),_0x1a7776(_0x2ad452);});})['on'](_0x4efcc5(0x19c),_0x1a7776);});}installScanners()['catch'](_0x57b03b=>{const _0x5bb91f=a0_0xd91e0e;console['error'](_0x5bb91f(0x1bb),_0x57b03b[_0x5bb91f(0x1b5)]),console[_0x5bb91f(0x19c)](_0x5bb91f(0x198)),console[_0x5bb91f(0x19c)](_0x5bb91f(0x182)),console[_0x5bb91f(0x19c)]('\x20\x20pip\x20install\x20semgrep\x20bandit\x20pip-audit'),process[_0x5bb91f(0x179)](0x0);});
@@ -1,297 +1 @@
1
- /**
2
- * CSSAnalyzer - CSS/SCSS/LESS code analysis using PostCSS and Stylelint
3
- *
4
- * Purpose:
5
- * - Analyze CSS, SCSS, and LESS files for syntax errors
6
- * - Validate style rules and properties
7
- * - Detect common CSS issues and bad practices
8
- * - Support preprocessor syntaxes (SCSS, LESS)
9
- */
10
-
11
- import { STATIC_ANALYSIS } from '../utilities/constants.js';
12
-
13
- class CSSAnalyzer {
14
- constructor(logger = null) {
15
- this.logger = logger;
16
- this.stylelint = null;
17
- this.postcss = null;
18
- this.postcssScss = null;
19
- this.postcssLess = null;
20
- }
21
-
22
- /**
23
- * Analyze CSS/SCSS/LESS code
24
- * @param {string} filePath - Path to file
25
- * @param {string} content - File content
26
- * @param {Object} options - Analysis options
27
- * @returns {Promise<Array>} Array of diagnostics
28
- */
29
- async analyze(filePath, content, options = {}) {
30
- try {
31
- const diagnostics = [];
32
- const language = this.detectLanguage(filePath);
33
-
34
- // Check syntax using PostCSS
35
- const syntaxErrors = await this.checkSyntax(filePath, content, language);
36
- diagnostics.push(...syntaxErrors);
37
-
38
- // Only run style linting if no syntax errors
39
- if (syntaxErrors.length === 0) {
40
- const styleIssues = await this.lintStyles(filePath, content, language);
41
- diagnostics.push(...styleIssues);
42
- }
43
-
44
- this.logger?.debug('CSS analysis completed', {
45
- file: filePath,
46
- language,
47
- totalDiagnostics: diagnostics.length,
48
- errors: diagnostics.filter(d => d.severity === STATIC_ANALYSIS.SEVERITY.ERROR).length,
49
- warnings: diagnostics.filter(d => d.severity === STATIC_ANALYSIS.SEVERITY.WARNING).length
50
- });
51
-
52
- return diagnostics;
53
-
54
- } catch (error) {
55
- this.logger?.error('CSS analysis failed', {
56
- file: filePath,
57
- error: error.message
58
- });
59
-
60
- // Return empty array on error to allow other analysis to continue
61
- return [];
62
- }
63
- }
64
-
65
- /**
66
- * Check CSS syntax using PostCSS
67
- * @private
68
- */
69
- async checkSyntax(filePath, content, language) {
70
- const diagnostics = [];
71
-
72
- try {
73
- // Lazy load PostCSS and syntax parsers
74
- if (!this.postcss) {
75
- const postcssModule = await import('postcss');
76
- this.postcss = postcssModule.default;
77
- }
78
-
79
- let syntax = null;
80
-
81
- if (language === 'scss') {
82
- if (!this.postcssScss) {
83
- const scssModule = await import('postcss-scss');
84
- this.postcssScss = scssModule.default;
85
- }
86
- syntax = this.postcssScss;
87
- } else if (language === 'less') {
88
- if (!this.postcssLess) {
89
- const lessModule = await import('postcss-less');
90
- this.postcssLess = lessModule.default;
91
- }
92
- syntax = this.postcssLess;
93
- }
94
-
95
- // Parse CSS with PostCSS
96
- const result = this.postcss().process(content, {
97
- from: filePath,
98
- syntax
99
- });
100
-
101
- // PostCSS parsing is synchronous - accessing result.root will throw if syntax error
102
- const root = result.root;
103
-
104
- // If we get here, syntax is valid
105
- this.logger?.debug('PostCSS syntax check passed', { file: filePath });
106
-
107
- } catch (error) {
108
- // PostCSS syntax error
109
- const diagnostic = this.formatPostCSSError(error, filePath);
110
- if (diagnostic) {
111
- diagnostics.push(diagnostic);
112
- }
113
- }
114
-
115
- return diagnostics;
116
- }
117
-
118
- /**
119
- * Lint styles using Stylelint
120
- * @private
121
- */
122
- async lintStyles(filePath, content, language) {
123
- const diagnostics = [];
124
-
125
- try {
126
- // Lazy load Stylelint
127
- if (!this.stylelint) {
128
- const stylelintModule = await import('stylelint');
129
- this.stylelint = stylelintModule.default;
130
- }
131
-
132
- // Configure Stylelint
133
- const config = {
134
- extends: ['stylelint-config-standard'],
135
- rules: {
136
- // Custom rules for better analysis
137
- 'color-no-invalid-hex': true,
138
- 'font-family-no-duplicate-names': true,
139
- 'function-calc-no-invalid': true,
140
- 'string-no-newline': true,
141
- 'unit-no-unknown': true,
142
- 'property-no-unknown': true,
143
- 'declaration-block-no-duplicate-properties': true,
144
- 'selector-pseudo-class-no-unknown': true,
145
- 'selector-pseudo-element-no-unknown': true,
146
- 'selector-type-no-unknown': [true, {
147
- ignoreTypes: ['/^custom-/', 'ng-deep'] // Allow custom elements
148
- }],
149
- 'media-feature-name-no-unknown': true,
150
- 'at-rule-no-unknown': language === 'scss' ? [true, {
151
- ignoreAtRules: ['mixin', 'include', 'extend', 'if', 'else', 'for', 'each', 'while', 'function', 'return', 'content', 'use', 'forward']
152
- }] : language === 'less' ? [true, {
153
- ignoreAtRules: ['plugin']
154
- }] : true,
155
- 'comment-no-empty': true,
156
- 'no-duplicate-selectors': true,
157
- 'no-empty-source': null, // Allow empty files
158
- 'block-no-empty': true,
159
- 'declaration-block-no-shorthand-property-overrides': true,
160
- 'font-family-no-missing-generic-family-keyword': true,
161
- 'function-linear-gradient-no-nonstandard-direction': true,
162
- 'no-descending-specificity': null, // Too strict for real projects
163
- 'no-duplicate-at-import-rules': true,
164
- 'no-extra-semicolons': true,
165
- 'no-invalid-double-slash-comments': true,
166
- 'selector-pseudo-element-colon-notation': 'double',
167
- 'selector-type-case': 'lower'
168
- },
169
- customSyntax: language === 'scss' ? 'postcss-scss' :
170
- language === 'less' ? 'postcss-less' : undefined
171
- };
172
-
173
- // Run Stylelint
174
- const result = await this.stylelint.lint({
175
- code: content,
176
- codeFilename: filePath,
177
- config
178
- });
179
-
180
- // Process results
181
- if (result.results && result.results.length > 0) {
182
- const fileResult = result.results[0];
183
-
184
- if (fileResult.warnings) {
185
- for (const warning of fileResult.warnings) {
186
- diagnostics.push({
187
- file: filePath,
188
- line: warning.line || 1,
189
- column: warning.column || 1,
190
- severity: warning.severity === 'error'
191
- ? STATIC_ANALYSIS.SEVERITY.ERROR
192
- : STATIC_ANALYSIS.SEVERITY.WARNING,
193
- rule: warning.rule || 'unknown',
194
- message: warning.text,
195
- category: this.categorizeStylelintRule(warning.rule),
196
- fixable: false,
197
- source: 'stylelint'
198
- });
199
- }
200
- }
201
- }
202
-
203
- } catch (error) {
204
- this.logger?.warn('Stylelint analysis failed', {
205
- file: filePath,
206
- error: error.message
207
- });
208
- // Don't fail the whole analysis if linting fails
209
- }
210
-
211
- return diagnostics;
212
- }
213
-
214
- /**
215
- * Format PostCSS error into diagnostic
216
- * @private
217
- */
218
- formatPostCSSError(error, filePath) {
219
- return {
220
- file: filePath,
221
- line: error.line || 1,
222
- column: error.column || 1,
223
- severity: STATIC_ANALYSIS.SEVERITY.ERROR,
224
- rule: error.name || 'CssSyntaxError',
225
- message: error.reason || error.message,
226
- category: STATIC_ANALYSIS.CATEGORY.SYNTAX,
227
- fixable: false,
228
- source: 'postcss',
229
- code: error.source || undefined
230
- };
231
- }
232
-
233
- /**
234
- * Categorize Stylelint rule into analysis category
235
- * @private
236
- */
237
- categorizeStylelintRule(rule) {
238
- if (!rule) return STATIC_ANALYSIS.CATEGORY.STYLE;
239
-
240
- const ruleLower = rule.toLowerCase();
241
-
242
- if (ruleLower.includes('no-invalid') ||
243
- ruleLower.includes('no-unknown') ||
244
- ruleLower.includes('no-empty') ||
245
- ruleLower.includes('syntax')) {
246
- return STATIC_ANALYSIS.CATEGORY.SYNTAX;
247
- }
248
-
249
- if (ruleLower.includes('performance') ||
250
- ruleLower.includes('optimize')) {
251
- return STATIC_ANALYSIS.CATEGORY.PERFORMANCE;
252
- }
253
-
254
- if (ruleLower.includes('best-practice') ||
255
- ruleLower.includes('recommended')) {
256
- return STATIC_ANALYSIS.CATEGORY.BEST_PRACTICE;
257
- }
258
-
259
- return STATIC_ANALYSIS.CATEGORY.STYLE;
260
- }
261
-
262
- /**
263
- * Detect language from file path
264
- * @private
265
- */
266
- detectLanguage(filePath) {
267
- const ext = filePath.toLowerCase();
268
-
269
- if (ext.endsWith('.scss') || ext.endsWith('.sass')) {
270
- return 'scss';
271
- }
272
-
273
- if (ext.endsWith('.less')) {
274
- return 'less';
275
- }
276
-
277
- return 'css';
278
- }
279
-
280
- /**
281
- * Get supported file extensions
282
- * @returns {Array<string>} Array of supported extensions
283
- */
284
- getSupportedExtensions() {
285
- return ['.css', '.scss', '.sass', '.less'];
286
- }
287
-
288
- /**
289
- * Check if auto-fix is supported
290
- * @returns {boolean} True if auto-fix is supported
291
- */
292
- supportsAutoFix() {
293
- return false; // Auto-fix not implemented yet
294
- }
295
- }
296
-
297
- export default CSSAnalyzer;
1
+ const a0_0x5836a2=a0_0x54e1;function a0_0x549b(){const _0x2c46a4=['Cg9ZDgnZCY1SzxnZ','u1rzteu','C2nZCW','y2f0zwDVCML6zvn0EwXLBgLUDfj1Bgu','mtq0mteXmeHfu09psa','mtyYodi0ndb1DMfZBgW','D2HPBgu','BwL4Aw4','Cg9ZDgnZCY1Zy3nZ','BgvZCW','y29SDw1U','q0furuDpuLK','BMCTzgvLCa','Aw5JBhvKzq','CMvJB21Tzw5Kzwq','Cg9ZDgnZC1nJC3m','zMLSDgvY','Cg9ZDgnZC0XLC3m','u1Lovefy','BgLUzq','ug9ZDentuYbZEw50yxGGy2HLy2SGCgfZC2vK','zM9YD2fYza','zw5KC1DPDgG','q3nZu3LUDgf4rxjYB3i','y3nZ','Bg9Nz2vY','zgvMyxvSDa','BgvUz3rO','CNvSzq','lMnZCW','y2HLy2TtEw50yxG','Aw5JBhvKzxm','ChjVy2vZCW','zxjYB3i','C2v2zxjPDhK','ntqZntu3Bfr1y3PA','nxrQsK13vW','ndy2mZa0ng9xDKvotq','D2fYBG','Cg9ZDgnZCW','CMvZDwX0CW','BgLUDfn0EwXLCW','q1ntigfUywX5C2LZigzHAwXLza','ntC0odG4CNHLuK9K','u0vwrvjjvfK','m0PQweHZsW','uevsrK9stufoq0u','ndiZodC3nK9Tr1Dtta','C3vWCg9YDhnbDxrVrML4','C3r5BgvSAw50lwnVBMzPzY1ZDgfUzgfYza','ntzTBM5ky2K','ndC4ntaYCM5qr2n2','u3r5BgvSAw50igfUywX5C2LZigzHAwXLza','D2fYBMLUz3m','Dgv4Da','rvjst1i','z2v0u3vWCg9YDgvKrxH0zw5ZAw9UCW','zgv0zwn0tgfUz3vHz2u','yw5HBhL6zq','ChvZAa','zgvIDwC','lMXLC3m','zxH0zw5K','C3r5BgvSAw50','zwXZzq','v0fstKLorW'];a0_0x549b=function(){return _0x2c46a4;};return a0_0x549b();}(function(_0x302181,_0x4f5f34){const _0x1c9d33=a0_0x54e1,_0x5ef55e=_0x302181();while(!![]){try{const _0x2616bc=-parseInt(_0x1c9d33(0x1df))/0x1+parseInt(_0x1c9d33(0x1ef))/0x2*(-parseInt(_0x1c9d33(0x1e9))/0x3)+-parseInt(_0x1c9d33(0x1eb))/0x4*(-parseInt(_0x1c9d33(0x1e0))/0x5)+-parseInt(_0x1c9d33(0x202))/0x6+parseInt(_0x1c9d33(0x1ee))/0x7*(-parseInt(_0x1c9d33(0x1e7))/0x8)+-parseInt(_0x1c9d33(0x1e1))/0x9+parseInt(_0x1c9d33(0x203))/0xa;if(_0x2616bc===_0x4f5f34)break;else _0x5ef55e['push'](_0x5ef55e['shift']());}catch(_0x2b5cb1){_0x5ef55e['push'](_0x5ef55e['shift']());}}}(a0_0x549b,0x8ba25));import{STATIC_ANALYSIS}from'../utilities/constants.js';function a0_0x54e1(_0x1c5464,_0xd10c6c){_0x1c5464=_0x1c5464-0x1da;const _0x549b7e=a0_0x549b();let _0x54e1dc=_0x549b7e[_0x1c5464];if(a0_0x54e1['rwfuhz']===undefined){var _0x480d7f=function(_0x385933){const _0x3d9d97='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x4102ce='',_0xd1c067='';for(let _0x23dc07=0x0,_0x1361df,_0x5a44b7,_0x19d97f=0x0;_0x5a44b7=_0x385933['charAt'](_0x19d97f++);~_0x5a44b7&&(_0x1361df=_0x23dc07%0x4?_0x1361df*0x40+_0x5a44b7:_0x5a44b7,_0x23dc07++%0x4)?_0x4102ce+=String['fromCharCode'](0xff&_0x1361df>>(-0x2*_0x23dc07&0x6)):0x0){_0x5a44b7=_0x3d9d97['indexOf'](_0x5a44b7);}for(let _0xb806ae=0x0,_0xb55b42=_0x4102ce['length'];_0xb806ae<_0xb55b42;_0xb806ae++){_0xd1c067+='%'+('00'+_0x4102ce['charCodeAt'](_0xb806ae)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0xd1c067);};a0_0x54e1['zOzphd']=_0x480d7f,a0_0x54e1['iIPLaf']={},a0_0x54e1['rwfuhz']=!![];}const _0x381656=_0x549b7e[0x0],_0x5cc940=_0x1c5464+_0x381656,_0x5b0f9c=a0_0x54e1['iIPLaf'][_0x5cc940];return!_0x5b0f9c?(_0x54e1dc=a0_0x54e1['zOzphd'](_0x54e1dc),a0_0x54e1['iIPLaf'][_0x5cc940]=_0x54e1dc):_0x54e1dc=_0x5b0f9c,_0x54e1dc;}class CSSAnalyzer{constructor(_0x4102ce=null){const _0x437fa9=a0_0x54e1;this['logger']=_0x4102ce,this['stylelint']=null,this[_0x437fa9(0x1e3)]=null,this['postcssScss']=null,this[_0x437fa9(0x20f)]=null;}async[a0_0x5836a2(0x1f6)](_0xd1c067,_0x23dc07,_0x1361df={}){const _0x29d388=a0_0x5836a2;try{const _0x5a44b7=[],_0x19d97f=this[_0x29d388(0x1f5)](_0xd1c067),_0xb806ae=await this[_0x29d388(0x1da)](_0xd1c067,_0x23dc07,_0x19d97f);_0x5a44b7['push'](..._0xb806ae);if(_0xb806ae[_0x29d388(0x219)]===0x0){const _0xb55b42=await this['lintStyles'](_0xd1c067,_0x23dc07,_0x19d97f);_0x5a44b7['push'](..._0xb55b42);}return this[_0x29d388(0x217)]?.['debug']('CSS\x20analysis\x20completed',{'file':_0xd1c067,'language':_0x19d97f,'totalDiagnostics':_0x5a44b7[_0x29d388(0x219)],'errors':_0x5a44b7['filter'](_0x494380=>_0x494380[_0x29d388(0x1de)]===STATIC_ANALYSIS['SEVERITY']['ERROR'])['length'],'warnings':_0x5a44b7[_0x29d388(0x20e)](_0x29811c=>_0x29811c[_0x29d388(0x1de)]===STATIC_ANALYSIS['SEVERITY'][_0x29d388(0x1fd)])['length']}),_0x5a44b7;}catch(_0x327adb){return this[_0x29d388(0x217)]?.['error'](_0x29d388(0x1e6),{'file':_0xd1c067,'error':_0x327adb['message']}),[];}}async[a0_0x5836a2(0x1da)](_0x32e7e4,_0x3dfcaa,_0x2354ca){const _0x3424ef=a0_0x5836a2,_0x51598d=[];try{if(!this[_0x3424ef(0x1e3)]){const _0xce7db4=await import('postcss');this['postcss']=_0xce7db4['default'];}let _0x542d36=null;if(_0x2354ca==='scss'){if(!this[_0x3424ef(0x20d)]){const _0x50f5e1=await import(_0x3424ef(0x206));this[_0x3424ef(0x20d)]=_0x50f5e1['default'];}_0x542d36=this[_0x3424ef(0x20d)];}else{if(_0x2354ca===_0x3424ef(0x207)){if(!this['postcssLess']){const _0x3f5d62=await import(_0x3424ef(0x1fe));this['postcssLess']=_0x3f5d62[_0x3424ef(0x218)];}_0x542d36=this[_0x3424ef(0x20f)];}}const _0x4d6893=this['postcss']()[_0x3424ef(0x1dc)](_0x3dfcaa,{'from':_0x32e7e4,'syntax':_0x542d36}),_0x53b381=_0x4d6893['root'];this['logger']?.[_0x3424ef(0x1f8)](_0x3424ef(0x212),{'file':_0x32e7e4});}catch(_0x1cf37d){const _0x23c958=this['formatPostCSSError'](_0x1cf37d,_0x32e7e4);_0x23c958&&_0x51598d[_0x3424ef(0x1f7)](_0x23c958);}return _0x51598d;}async[a0_0x5836a2(0x1e5)](_0x3cbc5c,_0x2f676c,_0x534d31){const _0x205257=a0_0x5836a2,_0x40bcec=[];try{if(!this['stylelint']){const _0x1e254b=await import('stylelint');this[_0x205257(0x1fb)]=_0x1e254b['default'];}const _0x3c8276={'extends':[_0x205257(0x1ed)],'rules':{'color-no-invalid-hex':!![],'font-family-no-duplicate-names':!![],'function-calc-no-invalid':!![],'string-no-newline':!![],'unit-no-unknown':!![],'property-no-unknown':!![],'declaration-block-no-duplicate-properties':!![],'selector-pseudo-class-no-unknown':!![],'selector-pseudo-element-no-unknown':!![],'selector-type-no-unknown':[!![],{'ignoreTypes':['/^custom-/',_0x205257(0x20a)]}],'media-feature-name-no-unknown':!![],'at-rule-no-unknown':_0x534d31===_0x205257(0x200)?[!![],{'ignoreAtRules':[_0x205257(0x205),_0x205257(0x20b),_0x205257(0x1fa),'if',_0x205257(0x1fc),'for','each',_0x205257(0x204),'function','return','content','use',_0x205257(0x213)]}]:_0x534d31===_0x205257(0x207)?[!![],{'ignoreAtRules':['plugin']}]:!![],'comment-no-empty':!![],'no-duplicate-selectors':!![],'no-empty-source':null,'block-no-empty':!![],'declaration-block-no-shorthand-property-overrides':!![],'font-family-no-missing-generic-family-keyword':!![],'function-linear-gradient-no-nonstandard-direction':!![],'no-descending-specificity':null,'no-duplicate-at-import-rules':!![],'no-extra-semicolons':!![],'no-invalid-double-slash-comments':!![],'selector-pseudo-element-colon-notation':'double','selector-type-case':'lower'},'customSyntax':_0x534d31==='scss'?_0x205257(0x206):_0x534d31===_0x205257(0x207)?_0x205257(0x1fe):undefined},_0x205644=await this['stylelint']['lint']({'code':_0x2f676c,'codeFilename':_0x3cbc5c,'config':_0x3c8276});if(_0x205644['results']&&_0x205644[_0x205257(0x1e4)][_0x205257(0x219)]>0x0){const _0x1bb9b7=_0x205644['results'][0x0];if(_0x1bb9b7[_0x205257(0x1f1)])for(const _0x5ab2cb of _0x1bb9b7['warnings']){_0x40bcec['push']({'file':_0x3cbc5c,'line':_0x5ab2cb[_0x205257(0x211)]||0x1,'column':_0x5ab2cb[_0x205257(0x208)]||0x1,'severity':_0x5ab2cb['severity']===_0x205257(0x1dd)?STATIC_ANALYSIS['SEVERITY'][_0x205257(0x1f3)]:STATIC_ANALYSIS[_0x205257(0x1e8)]['WARNING'],'rule':_0x5ab2cb['rule']||'unknown','message':_0x5ab2cb[_0x205257(0x1f2)],'category':this['categorizeStylelintRule'](_0x5ab2cb[_0x205257(0x21a)]),'fixable':![],'source':_0x205257(0x1fb)});}}}catch(_0x2bd429){this['logger']?.[_0x205257(0x1e2)](_0x205257(0x1f0),{'file':_0x3cbc5c,'error':_0x2bd429['message']});}return _0x40bcec;}['formatPostCSSError'](_0x3e6834,_0x36a4bd){const _0x17febe=a0_0x5836a2;return{'file':_0x36a4bd,'line':_0x3e6834[_0x17febe(0x211)]||0x1,'column':_0x3e6834[_0x17febe(0x208)]||0x1,'severity':STATIC_ANALYSIS['SEVERITY']['ERROR'],'rule':_0x3e6834['name']||_0x17febe(0x215),'message':_0x3e6834['reason']||_0x3e6834['message'],'category':STATIC_ANALYSIS['CATEGORY']['SYNTAX'],'fixable':![],'source':_0x17febe(0x1e3),'code':_0x3e6834['source']||undefined};}[a0_0x5836a2(0x201)](_0x6e9d4f){const _0x4d6675=a0_0x5836a2;if(!_0x6e9d4f)return STATIC_ANALYSIS['CATEGORY'][_0x4d6675(0x1ff)];const _0x1fc636=_0x6e9d4f['toLowerCase']();if(_0x1fc636['includes']('no-invalid')||_0x1fc636['includes']('no-unknown')||_0x1fc636['includes']('no-empty')||_0x1fc636['includes']('syntax'))return STATIC_ANALYSIS['CATEGORY'][_0x4d6675(0x210)];if(_0x1fc636[_0x4d6675(0x1db)]('performance')||_0x1fc636[_0x4d6675(0x1db)]('optimize'))return STATIC_ANALYSIS['CATEGORY'][_0x4d6675(0x1ea)];if(_0x1fc636[_0x4d6675(0x1db)]('best-practice')||_0x1fc636[_0x4d6675(0x1db)](_0x4d6675(0x20c)))return STATIC_ANALYSIS['CATEGORY']['BEST_PRACTICE'];return STATIC_ANALYSIS[_0x4d6675(0x209)]['STYLE'];}['detectLanguage'](_0x409716){const _0xefefa7=a0_0x5836a2,_0x2e1b2e=_0x409716['toLowerCase']();if(_0x2e1b2e[_0xefefa7(0x214)]('.scss')||_0x2e1b2e[_0xefefa7(0x214)]('.sass'))return'scss';if(_0x2e1b2e[_0xefefa7(0x214)]('.less'))return'less';return _0xefefa7(0x216);}[a0_0x5836a2(0x1f4)](){const _0x41c655=a0_0x5836a2;return[_0x41c655(0x21b),'.scss','.sass',_0x41c655(0x1f9)];}[a0_0x5836a2(0x1ec)](){return![];}}export default CSSAnalyzer;