@houtini/lm 1.0.0

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 (260) hide show
  1. package/CHANGELOG.md +273 -0
  2. package/LICENSE +21 -0
  3. package/README.md +203 -0
  4. package/dist/cache/analysis-cache.d.ts +33 -0
  5. package/dist/cache/analysis-cache.d.ts.map +1 -0
  6. package/dist/cache/analysis-cache.js +56 -0
  7. package/dist/cache/analysis-cache.js.map +1 -0
  8. package/dist/cache/cache-manager.d.ts +29 -0
  9. package/dist/cache/cache-manager.d.ts.map +1 -0
  10. package/dist/cache/cache-manager.js +85 -0
  11. package/dist/cache/cache-manager.js.map +1 -0
  12. package/dist/cache/index.d.ts +16 -0
  13. package/dist/cache/index.d.ts.map +1 -0
  14. package/dist/cache/index.js +17 -0
  15. package/dist/cache/index.js.map +1 -0
  16. package/dist/cache/prompt-cache.d.ts +33 -0
  17. package/dist/cache/prompt-cache.d.ts.map +1 -0
  18. package/dist/cache/prompt-cache.js +61 -0
  19. package/dist/cache/prompt-cache.js.map +1 -0
  20. package/dist/config.d.ts +43 -0
  21. package/dist/config.d.ts.map +1 -0
  22. package/dist/config.js +70 -0
  23. package/dist/config.js.map +1 -0
  24. package/dist/core/ThreeStagePromptManager.d.ts +39 -0
  25. package/dist/core/ThreeStagePromptManager.d.ts.map +1 -0
  26. package/dist/core/ThreeStagePromptManager.js +176 -0
  27. package/dist/core/ThreeStagePromptManager.js.map +1 -0
  28. package/dist/index.d.ts +6 -0
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.js +230 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/plugins/base-plugin.d.ts +47 -0
  33. package/dist/plugins/base-plugin.d.ts.map +1 -0
  34. package/dist/plugins/base-plugin.js +90 -0
  35. package/dist/plugins/base-plugin.js.map +1 -0
  36. package/dist/plugins/index.d.ts +58 -0
  37. package/dist/plugins/index.d.ts.map +1 -0
  38. package/dist/plugins/index.js +161 -0
  39. package/dist/plugins/index.js.map +1 -0
  40. package/dist/plugins/types.d.ts +5 -0
  41. package/dist/plugins/types.d.ts.map +1 -0
  42. package/dist/plugins/types.js +5 -0
  43. package/dist/plugins/types.js.map +1 -0
  44. package/dist/prompts/analyze/code-quality.d.ts +116 -0
  45. package/dist/prompts/analyze/code-quality.d.ts.map +1 -0
  46. package/dist/prompts/analyze/code-quality.js +433 -0
  47. package/dist/prompts/analyze/code-quality.js.map +1 -0
  48. package/dist/prompts/analyze/compare-integration.d.ts +130 -0
  49. package/dist/prompts/analyze/compare-integration.d.ts.map +1 -0
  50. package/dist/prompts/analyze/compare-integration.js +543 -0
  51. package/dist/prompts/analyze/compare-integration.js.map +1 -0
  52. package/dist/prompts/analyze/count-files.d.ts +109 -0
  53. package/dist/prompts/analyze/count-files.d.ts.map +1 -0
  54. package/dist/prompts/analyze/count-files.js +399 -0
  55. package/dist/prompts/analyze/count-files.js.map +1 -0
  56. package/dist/prompts/analyze/database-queries.d.ts +156 -0
  57. package/dist/prompts/analyze/database-queries.d.ts.map +1 -0
  58. package/dist/prompts/analyze/database-queries.js +759 -0
  59. package/dist/prompts/analyze/database-queries.js.map +1 -0
  60. package/dist/prompts/analyze/dependencies.d.ts +97 -0
  61. package/dist/prompts/analyze/dependencies.d.ts.map +1 -0
  62. package/dist/prompts/analyze/dependencies.js +333 -0
  63. package/dist/prompts/analyze/dependencies.js.map +1 -0
  64. package/dist/prompts/analyze/diff-signatures.d.ts +139 -0
  65. package/dist/prompts/analyze/diff-signatures.d.ts.map +1 -0
  66. package/dist/prompts/analyze/diff-signatures.js +702 -0
  67. package/dist/prompts/analyze/diff-signatures.js.map +1 -0
  68. package/dist/prompts/analyze/find-patterns.d.ts +128 -0
  69. package/dist/prompts/analyze/find-patterns.d.ts.map +1 -0
  70. package/dist/prompts/analyze/find-patterns.js +520 -0
  71. package/dist/prompts/analyze/find-patterns.js.map +1 -0
  72. package/dist/prompts/analyze/find-unused-css.d.ts +151 -0
  73. package/dist/prompts/analyze/find-unused-css.d.ts.map +1 -0
  74. package/dist/prompts/analyze/find-unused-css.js +754 -0
  75. package/dist/prompts/analyze/find-unused-css.js.map +1 -0
  76. package/dist/prompts/analyze/n8n-workflow.d.ts +137 -0
  77. package/dist/prompts/analyze/n8n-workflow.d.ts.map +1 -0
  78. package/dist/prompts/analyze/n8n-workflow.js +529 -0
  79. package/dist/prompts/analyze/n8n-workflow.js.map +1 -0
  80. package/dist/prompts/analyze/project-structure.d.ts +126 -0
  81. package/dist/prompts/analyze/project-structure.d.ts.map +1 -0
  82. package/dist/prompts/analyze/project-structure.js +569 -0
  83. package/dist/prompts/analyze/project-structure.js.map +1 -0
  84. package/dist/prompts/analyze/security-audit.d.ts +142 -0
  85. package/dist/prompts/analyze/security-audit.d.ts.map +1 -0
  86. package/dist/prompts/analyze/security-audit.js +637 -0
  87. package/dist/prompts/analyze/security-audit.js.map +1 -0
  88. package/dist/prompts/analyze/single-file.d.ts +162 -0
  89. package/dist/prompts/analyze/single-file.d.ts.map +1 -0
  90. package/dist/prompts/analyze/single-file.js +665 -0
  91. package/dist/prompts/analyze/single-file.js.map +1 -0
  92. package/dist/prompts/analyze/trace-execution.d.ts +126 -0
  93. package/dist/prompts/analyze/trace-execution.d.ts.map +1 -0
  94. package/dist/prompts/analyze/trace-execution.js +609 -0
  95. package/dist/prompts/analyze/trace-execution.js.map +1 -0
  96. package/dist/prompts/analyze/wordpress-plugin-audit.d.ts +116 -0
  97. package/dist/prompts/analyze/wordpress-plugin-audit.d.ts.map +1 -0
  98. package/dist/prompts/analyze/wordpress-plugin-audit.js +454 -0
  99. package/dist/prompts/analyze/wordpress-plugin-audit.js.map +1 -0
  100. package/dist/prompts/analyze/wordpress-security.d.ts +146 -0
  101. package/dist/prompts/analyze/wordpress-security.d.ts.map +1 -0
  102. package/dist/prompts/analyze/wordpress-security.js +698 -0
  103. package/dist/prompts/analyze/wordpress-security.js.map +1 -0
  104. package/dist/prompts/analyze/wordpress-theme-audit.d.ts +114 -0
  105. package/dist/prompts/analyze/wordpress-theme-audit.d.ts.map +1 -0
  106. package/dist/prompts/analyze/wordpress-theme-audit.js +538 -0
  107. package/dist/prompts/analyze/wordpress-theme-audit.js.map +1 -0
  108. package/dist/prompts/custom/custom-prompt.d.ts +135 -0
  109. package/dist/prompts/custom/custom-prompt.d.ts.map +1 -0
  110. package/dist/prompts/custom/custom-prompt.js +419 -0
  111. package/dist/prompts/custom/custom-prompt.js.map +1 -0
  112. package/dist/prompts/fun/arcade-game.d.ts +152 -0
  113. package/dist/prompts/fun/arcade-game.d.ts.map +1 -0
  114. package/dist/prompts/fun/arcade-game.js +653 -0
  115. package/dist/prompts/fun/arcade-game.js.map +1 -0
  116. package/dist/prompts/fun/create_text_adventure.d.ts +100 -0
  117. package/dist/prompts/fun/create_text_adventure.d.ts.map +1 -0
  118. package/dist/prompts/fun/create_text_adventure.js +397 -0
  119. package/dist/prompts/fun/create_text_adventure.js.map +1 -0
  120. package/dist/prompts/fun/css-art-generator.d.ts +168 -0
  121. package/dist/prompts/fun/css-art-generator.d.ts.map +1 -0
  122. package/dist/prompts/fun/css-art-generator.js +827 -0
  123. package/dist/prompts/fun/css-art-generator.js.map +1 -0
  124. package/dist/prompts/generate/project-documentation.d.ts +137 -0
  125. package/dist/prompts/generate/project-documentation.d.ts.map +1 -0
  126. package/dist/prompts/generate/project-documentation.js +666 -0
  127. package/dist/prompts/generate/project-documentation.js.map +1 -0
  128. package/dist/prompts/generate/refactoring.d.ts +164 -0
  129. package/dist/prompts/generate/refactoring.d.ts.map +1 -0
  130. package/dist/prompts/generate/refactoring.js +621 -0
  131. package/dist/prompts/generate/refactoring.js.map +1 -0
  132. package/dist/prompts/generate/responsive-component.d.ts +147 -0
  133. package/dist/prompts/generate/responsive-component.d.ts.map +1 -0
  134. package/dist/prompts/generate/responsive-component.js +955 -0
  135. package/dist/prompts/generate/responsive-component.js.map +1 -0
  136. package/dist/prompts/generate/typescript-conversion.d.ts +144 -0
  137. package/dist/prompts/generate/typescript-conversion.d.ts.map +1 -0
  138. package/dist/prompts/generate/typescript-conversion.js +527 -0
  139. package/dist/prompts/generate/typescript-conversion.js.map +1 -0
  140. package/dist/prompts/generate/unit-tests.d.ts +139 -0
  141. package/dist/prompts/generate/unit-tests.d.ts.map +1 -0
  142. package/dist/prompts/generate/unit-tests.js +578 -0
  143. package/dist/prompts/generate/unit-tests.js.map +1 -0
  144. package/dist/prompts/generate/wordpress-plugin.d.ts +179 -0
  145. package/dist/prompts/generate/wordpress-plugin.d.ts.map +1 -0
  146. package/dist/prompts/generate/wordpress-plugin.js +763 -0
  147. package/dist/prompts/generate/wordpress-plugin.js.map +1 -0
  148. package/dist/prompts/generate/wordpress-theme-from-static.d.ts +177 -0
  149. package/dist/prompts/generate/wordpress-theme-from-static.d.ts.map +1 -0
  150. package/dist/prompts/generate/wordpress-theme-from-static.js +695 -0
  151. package/dist/prompts/generate/wordpress-theme-from-static.js.map +1 -0
  152. package/dist/prompts/shared/cache-manager.d.ts +45 -0
  153. package/dist/prompts/shared/cache-manager.d.ts.map +1 -0
  154. package/dist/prompts/shared/cache-manager.js +129 -0
  155. package/dist/prompts/shared/cache-manager.js.map +1 -0
  156. package/dist/prompts/shared/helpers.d.ts +39 -0
  157. package/dist/prompts/shared/helpers.d.ts.map +1 -0
  158. package/dist/prompts/shared/helpers.js +151 -0
  159. package/dist/prompts/shared/helpers.js.map +1 -0
  160. package/dist/prompts/shared/templates.d.ts +35 -0
  161. package/dist/prompts/shared/templates.d.ts.map +1 -0
  162. package/dist/prompts/shared/templates.js +77 -0
  163. package/dist/prompts/shared/templates.js.map +1 -0
  164. package/dist/prompts/shared/types.d.ts +112 -0
  165. package/dist/prompts/shared/types.d.ts.map +1 -0
  166. package/dist/prompts/shared/types.js +5 -0
  167. package/dist/prompts/shared/types.js.map +1 -0
  168. package/dist/prompts/system/find-unused-files.d.ts +106 -0
  169. package/dist/prompts/system/find-unused-files.d.ts.map +1 -0
  170. package/dist/prompts/system/find-unused-files.js +353 -0
  171. package/dist/prompts/system/find-unused-files.js.map +1 -0
  172. package/dist/security/index.d.ts +39 -0
  173. package/dist/security/index.d.ts.map +1 -0
  174. package/dist/security/index.js +46 -0
  175. package/dist/security/index.js.map +1 -0
  176. package/dist/security/integration-helpers.d.ts +121 -0
  177. package/dist/security/integration-helpers.d.ts.map +1 -0
  178. package/dist/security/integration-helpers.js +190 -0
  179. package/dist/security/integration-helpers.js.map +1 -0
  180. package/dist/security/output-encoder.d.ts +94 -0
  181. package/dist/security/output-encoder.d.ts.map +1 -0
  182. package/dist/security/output-encoder.js +295 -0
  183. package/dist/security/output-encoder.js.map +1 -0
  184. package/dist/security/prompt-injection-guard.d.ts +59 -0
  185. package/dist/security/prompt-injection-guard.d.ts.map +1 -0
  186. package/dist/security/prompt-injection-guard.js +249 -0
  187. package/dist/security/prompt-injection-guard.js.map +1 -0
  188. package/dist/security/sanitisation.d.ts +67 -0
  189. package/dist/security/sanitisation.d.ts.map +1 -0
  190. package/dist/security/sanitisation.js +398 -0
  191. package/dist/security/sanitisation.js.map +1 -0
  192. package/dist/security/security-service.d.ts +103 -0
  193. package/dist/security/security-service.d.ts.map +1 -0
  194. package/dist/security/security-service.js +303 -0
  195. package/dist/security/security-service.js.map +1 -0
  196. package/dist/security-config.d.ts +45 -0
  197. package/dist/security-config.d.ts.map +1 -0
  198. package/dist/security-config.js +63 -0
  199. package/dist/security-config.js.map +1 -0
  200. package/dist/system/function-list.d.ts +61 -0
  201. package/dist/system/function-list.d.ts.map +1 -0
  202. package/dist/system/function-list.js +111 -0
  203. package/dist/system/function-list.js.map +1 -0
  204. package/dist/system/function-registry.d.ts +23 -0
  205. package/dist/system/function-registry.d.ts.map +1 -0
  206. package/dist/system/function-registry.js +136 -0
  207. package/dist/system/function-registry.js.map +1 -0
  208. package/dist/system/health-check.d.ts +33 -0
  209. package/dist/system/health-check.d.ts.map +1 -0
  210. package/dist/system/health-check.js +98 -0
  211. package/dist/system/health-check.js.map +1 -0
  212. package/dist/system/path-resolver.d.ts +55 -0
  213. package/dist/system/path-resolver.d.ts.map +1 -0
  214. package/dist/system/path-resolver.js +90 -0
  215. package/dist/system/path-resolver.js.map +1 -0
  216. package/dist/templates/plugin-template.d.ts +121 -0
  217. package/dist/templates/plugin-template.d.ts.map +1 -0
  218. package/dist/templates/plugin-template.js +450 -0
  219. package/dist/templates/plugin-template.js.map +1 -0
  220. package/dist/types/chunking-types.d.ts +88 -0
  221. package/dist/types/chunking-types.d.ts.map +1 -0
  222. package/dist/types/chunking-types.js +18 -0
  223. package/dist/types/chunking-types.js.map +1 -0
  224. package/dist/types/prompt-stages.d.ts +42 -0
  225. package/dist/types/prompt-stages.d.ts.map +1 -0
  226. package/dist/types/prompt-stages.js +6 -0
  227. package/dist/types/prompt-stages.js.map +1 -0
  228. package/dist/types.d.ts +46 -0
  229. package/dist/types.d.ts.map +1 -0
  230. package/dist/types.js +6 -0
  231. package/dist/types.js.map +1 -0
  232. package/dist/utils/css-parser.d.ts +26 -0
  233. package/dist/utils/css-parser.d.ts.map +1 -0
  234. package/dist/utils/css-parser.js +117 -0
  235. package/dist/utils/css-parser.js.map +1 -0
  236. package/dist/utils/path-resolver.d.ts +13 -0
  237. package/dist/utils/path-resolver.d.ts.map +1 -0
  238. package/dist/utils/path-resolver.js +78 -0
  239. package/dist/utils/path-resolver.js.map +1 -0
  240. package/dist/utils/plugin-utilities.d.ts +171 -0
  241. package/dist/utils/plugin-utilities.d.ts.map +1 -0
  242. package/dist/utils/plugin-utilities.js +221 -0
  243. package/dist/utils/plugin-utilities.js.map +1 -0
  244. package/dist/utils/streamHandler.d.ts +3 -0
  245. package/dist/utils/streamHandler.d.ts.map +1 -0
  246. package/dist/utils/streamHandler.js +137 -0
  247. package/dist/utils/streamHandler.js.map +1 -0
  248. package/dist/validation/output-validator.d.ts +136 -0
  249. package/dist/validation/output-validator.d.ts.map +1 -0
  250. package/dist/validation/output-validator.js +262 -0
  251. package/dist/validation/output-validator.js.map +1 -0
  252. package/dist/validation/response-factory.d.ts +44 -0
  253. package/dist/validation/response-factory.d.ts.map +1 -0
  254. package/dist/validation/response-factory.js +202 -0
  255. package/dist/validation/response-factory.js.map +1 -0
  256. package/dist/validation/schemas.d.ts +519 -0
  257. package/dist/validation/schemas.d.ts.map +1 -0
  258. package/dist/validation/schemas.js +6 -0
  259. package/dist/validation/schemas.js.map +1 -0
  260. package/package.json +72 -0
@@ -0,0 +1,754 @@
1
+ import { BasePlugin } from '../../plugins/base-plugin.js';
2
+ import { ThreeStagePromptManager } from '../../core/ThreeStagePromptManager.js';
3
+ import { withSecurity } from '../../security/integration-helpers.js';
4
+ import { readFileContent } from '../shared/helpers.js';
5
+ import { ModelSetup, ResponseProcessor, ParameterValidator, ErrorHandler, MultiFileAnalysis } from '../../utils/plugin-utilities.js';
6
+ import { getAnalysisCache } from '../../cache/index.js';
7
+ import { CssParser } from '../../utils/css-parser.js';
8
+ // Common Node.js modules
9
+ import { basename, relative } from 'path';
10
+ import { readFile } from 'fs/promises';
11
+ export class FindUnusedCSSAnalyzer extends BasePlugin {
12
+ constructor() {
13
+ super();
14
+ this.name = 'find_unused_css';
15
+ this.category = 'analyze';
16
+ this.description = 'Analyze CSS usage and identify unused selectors for performance optimization. Supports both URL analysis and local file analysis.';
17
+ // Universal parameter set - supports both URL and local file scenarios
18
+ this.parameters = {
19
+ // URL analysis
20
+ url: {
21
+ type: 'string',
22
+ description: 'URL to analyze for CSS usage (single page)',
23
+ required: false
24
+ },
25
+ // Single-file parameters
26
+ cssPath: {
27
+ type: 'string',
28
+ description: 'Path to CSS file to analyze',
29
+ required: false
30
+ },
31
+ htmlPath: {
32
+ type: 'string',
33
+ description: 'Path to HTML file to check CSS usage against',
34
+ required: false
35
+ },
36
+ code: {
37
+ type: 'string',
38
+ description: 'CSS code to analyze (for single-code analysis)',
39
+ required: false
40
+ },
41
+ // Multi-file parameters
42
+ projectPath: {
43
+ type: 'string',
44
+ description: 'Path to project directory containing HTML/CSS files',
45
+ required: false
46
+ },
47
+ files: {
48
+ type: 'array',
49
+ description: 'Specific HTML/CSS file paths to analyze',
50
+ required: false,
51
+ items: { type: 'string' }
52
+ },
53
+ maxDepth: {
54
+ type: 'number',
55
+ description: 'Maximum directory depth for file discovery',
56
+ required: false,
57
+ default: 3
58
+ },
59
+ // Analysis options
60
+ analysisDepth: {
61
+ type: 'string',
62
+ description: 'Level of analysis detail',
63
+ enum: ['basic', 'detailed', 'comprehensive'],
64
+ default: 'detailed',
65
+ required: false
66
+ },
67
+ analysisType: {
68
+ type: 'string',
69
+ description: 'Type of CSS analysis to perform',
70
+ enum: ['performance', 'usage', 'comprehensive'],
71
+ default: 'comprehensive',
72
+ required: false
73
+ },
74
+ includeMediaQueries: {
75
+ type: 'boolean',
76
+ description: 'Include media query analysis',
77
+ default: true,
78
+ required: false
79
+ },
80
+ ignorePseudoSelectors: {
81
+ type: 'boolean',
82
+ description: 'Ignore pseudo-selectors like :hover, :focus',
83
+ default: false,
84
+ required: false
85
+ },
86
+ // Compatibility
87
+ language: {
88
+ type: 'string',
89
+ description: 'File language (css, html)',
90
+ required: false,
91
+ default: 'css'
92
+ },
93
+ filePath: {
94
+ type: 'string',
95
+ description: 'Path to CSS file to analyze',
96
+ required: false
97
+ }
98
+ };
99
+ this.analysisCache = getAnalysisCache();
100
+ this.multiFileAnalysis = new MultiFileAnalysis();
101
+ }
102
+ async execute(params, llmClient) {
103
+ return await withSecurity(this, params, llmClient, async (secureParams) => {
104
+ try {
105
+ // 1. Auto-detect analysis mode based on parameters
106
+ const analysisMode = this.detectAnalysisMode(secureParams);
107
+ // 2. Validate parameters based on detected mode
108
+ this.validateParameters(secureParams, analysisMode);
109
+ // 3. Setup model
110
+ const { model, contextLength } = await ModelSetup.getReadyModel(llmClient);
111
+ // 4. Route to appropriate analysis method
112
+ if (analysisMode === 'url') {
113
+ return await this.executeURLAnalysis(secureParams, model, contextLength);
114
+ }
115
+ else if (analysisMode === 'single-file') {
116
+ return await this.executeSingleFileAnalysis(secureParams, model, contextLength);
117
+ }
118
+ else {
119
+ return await this.executeMultiFileAnalysis(secureParams, model, contextLength);
120
+ }
121
+ }
122
+ catch (error) {
123
+ return ErrorHandler.createExecutionError('find_unused_css', error);
124
+ }
125
+ });
126
+ }
127
+ /**
128
+ * Auto-detect whether this is URL, single-file or multi-file analysis
129
+ */
130
+ detectAnalysisMode(params) {
131
+ // URL analysis takes priority
132
+ if (params.url) {
133
+ return 'url';
134
+ }
135
+ // Single-file indicators (CSS + optional HTML)
136
+ if (params.code || params.cssPath || params.filePath) {
137
+ return 'single-file';
138
+ }
139
+ // Multi-file indicators
140
+ if (params.projectPath || params.files) {
141
+ return 'multi-file';
142
+ }
143
+ // Default to single-file for CSS analysis
144
+ return 'single-file';
145
+ }
146
+ /**
147
+ * Validate parameters based on detected analysis mode
148
+ */
149
+ validateParameters(params, mode) {
150
+ if (mode === 'url') {
151
+ if (!params.url) {
152
+ throw new Error('URL parameter is required for URL analysis');
153
+ }
154
+ }
155
+ else if (mode === 'single-file') {
156
+ if (!params.code && !params.cssPath && !params.filePath) {
157
+ throw new Error('Either code, cssPath, or filePath is required for single-file analysis');
158
+ }
159
+ }
160
+ else {
161
+ ParameterValidator.validateProjectPath(params);
162
+ ParameterValidator.validateDepth(params);
163
+ }
164
+ // Universal validations
165
+ ParameterValidator.validateEnum(params, 'analysisType', ['performance', 'usage', 'comprehensive']);
166
+ ParameterValidator.validateEnum(params, 'analysisDepth', ['basic', 'detailed', 'comprehensive']);
167
+ }
168
+ /**
169
+ * Execute URL analysis: Puppeteer -> CSS Parser -> Houtini LM
170
+ */
171
+ async executeURLAnalysis(params, model, contextLength) {
172
+ // Step 1: Extract data from URL using Puppeteer
173
+ const urlData = await this.extractURLDataWithPuppeteer(params.url);
174
+ // Step 2: Process CSS with our utility
175
+ const processedCSSData = this.processCSSData(urlData);
176
+ // Step 3: Generate prompt stages for Houtini LM
177
+ const promptStages = this.getURLAnalysisPromptStages({
178
+ ...params,
179
+ urlData: processedCSSData
180
+ });
181
+ // Step 4: Execute with proper chunking
182
+ const promptManager = new ThreeStagePromptManager(contextLength);
183
+ const needsChunking = promptManager.needsChunking(promptStages);
184
+ if (needsChunking) {
185
+ const conversation = promptManager.createChunkedConversation(promptStages);
186
+ const messages = [
187
+ conversation.systemMessage,
188
+ ...conversation.dataMessages,
189
+ conversation.analysisMessage
190
+ ];
191
+ return await ResponseProcessor.executeChunked(messages, model, contextLength, 'find_unused_css', 'single');
192
+ }
193
+ else {
194
+ return await ResponseProcessor.executeDirect(promptStages, model, contextLength, 'find_unused_css');
195
+ }
196
+ }
197
+ /**
198
+ * Execute single-file analysis: File -> CSS Parser -> Houtini LM
199
+ */
200
+ async executeSingleFileAnalysis(params, model, contextLength) {
201
+ // Step 1: Process CSS input
202
+ let cssContent = params.code;
203
+ if (params.cssPath || params.filePath) {
204
+ const filePath = params.cssPath || params.filePath;
205
+ cssContent = await readFileContent(filePath);
206
+ }
207
+ // Step 2: Process optional HTML input
208
+ let htmlContent = '';
209
+ if (params.htmlPath) {
210
+ htmlContent = await readFileContent(params.htmlPath);
211
+ }
212
+ // Step 3: Process with CSS Parser utility
213
+ const processedData = this.processLocalCSSData(cssContent, htmlContent, params);
214
+ // Step 4: Generate prompt stages
215
+ const promptStages = this.getSingleFilePromptStages({
216
+ ...params,
217
+ processedData
218
+ });
219
+ // Step 5: Execute with proper chunking
220
+ const promptManager = new ThreeStagePromptManager(contextLength);
221
+ const needsChunking = promptManager.needsChunking(promptStages);
222
+ if (needsChunking) {
223
+ const conversation = promptManager.createChunkedConversation(promptStages);
224
+ const messages = [
225
+ conversation.systemMessage,
226
+ ...conversation.dataMessages,
227
+ conversation.analysisMessage
228
+ ];
229
+ return await ResponseProcessor.executeChunked(messages, model, contextLength, 'find_unused_css', 'single');
230
+ }
231
+ else {
232
+ return await ResponseProcessor.executeDirect(promptStages, model, contextLength, 'find_unused_css');
233
+ }
234
+ }
235
+ /**
236
+ * Execute multi-file analysis
237
+ */
238
+ async executeMultiFileAnalysis(params, model, contextLength) {
239
+ // Discover files
240
+ let filesToAnalyze = params.files ||
241
+ await this.discoverRelevantFiles(params.projectPath, params.maxDepth, params.analysisType);
242
+ // Perform multi-file analysis with caching
243
+ const analysisResult = await this.performMultiFileAnalysis(filesToAnalyze, params, model, contextLength);
244
+ const promptStages = this.getMultiFilePromptStages({
245
+ ...params,
246
+ analysisResult,
247
+ fileCount: filesToAnalyze.length
248
+ });
249
+ // Always use chunking for multi-file
250
+ const promptManager = new ThreeStagePromptManager(contextLength);
251
+ const conversation = promptManager.createChunkedConversation(promptStages);
252
+ const messages = [
253
+ conversation.systemMessage,
254
+ ...conversation.dataMessages,
255
+ conversation.analysisMessage
256
+ ];
257
+ return await ResponseProcessor.executeChunked(messages, model, contextLength, 'find_unused_css', 'multifile');
258
+ }
259
+ /**
260
+ * Extract data from URL using Puppeteer (runs before LLM)
261
+ */
262
+ async extractURLDataWithPuppeteer(url) {
263
+ const puppeteer = await import('puppeteer');
264
+ const browser = await puppeteer.launch({
265
+ headless: true,
266
+ args: ['--no-sandbox', '--disable-setuid-sandbox']
267
+ });
268
+ try {
269
+ const page = await browser.newPage();
270
+ await page.goto(url, { waitUntil: 'networkidle0', timeout: 30000 });
271
+ // Extract HTML content
272
+ const htmlContent = await page.content();
273
+ // Extract all CSS rules from stylesheets
274
+ const cssData = await page.evaluate(() => {
275
+ const cssRules = [];
276
+ const usedSelectors = new Set();
277
+ // Get all stylesheets - use any to bypass TypeScript DOM checks
278
+ const stylesheets = Array.from(globalThis.document.styleSheets);
279
+ stylesheets.forEach((stylesheet) => {
280
+ try {
281
+ const rules = Array.from(stylesheet.cssRules || []);
282
+ rules.forEach((rule) => {
283
+ if (rule.selectorText) {
284
+ cssRules.push({
285
+ selector: rule.selectorText,
286
+ cssText: rule.cssText,
287
+ sourceHref: stylesheet.href || 'inline',
288
+ media: rule.media ? rule.media.mediaText : null
289
+ });
290
+ }
291
+ });
292
+ }
293
+ catch (e) {
294
+ // Skip CORS-protected stylesheets - note this limitation
295
+ }
296
+ });
297
+ // Test each selector to see if it's used
298
+ cssRules.forEach(rule => {
299
+ try {
300
+ const elements = globalThis.document.querySelectorAll(rule.selector);
301
+ if (elements.length > 0) {
302
+ usedSelectors.add(rule.selector);
303
+ }
304
+ }
305
+ catch (e) {
306
+ // Invalid selector - mark as potentially unused
307
+ }
308
+ });
309
+ return {
310
+ totalRules: cssRules.length,
311
+ totalUsed: usedSelectors.size,
312
+ rules: cssRules.map(rule => ({
313
+ ...rule,
314
+ isUsed: usedSelectors.has(rule.selector)
315
+ })),
316
+ pageTitle: globalThis.document.title,
317
+ pageUrl: globalThis.window.location.href
318
+ };
319
+ });
320
+ return {
321
+ url,
322
+ htmlContent,
323
+ cssData,
324
+ timestamp: new Date().toISOString()
325
+ };
326
+ }
327
+ finally {
328
+ await browser.close();
329
+ }
330
+ }
331
+ /**
332
+ * Process CSS data using our CSS parser utility
333
+ */
334
+ processCSSData(urlData) {
335
+ const { cssData, htmlContent } = urlData;
336
+ // Use our CSS parser to get additional analysis
337
+ const frameworks = CssParser.detectBasicFrameworks(htmlContent);
338
+ // Process each stylesheet's rules
339
+ const processedRules = cssData.rules.map((rule) => {
340
+ return {
341
+ selector: rule.selector,
342
+ isUsed: rule.isUsed,
343
+ source: rule.sourceHref,
344
+ media: rule.media,
345
+ cssText: rule.cssText
346
+ };
347
+ });
348
+ // Group by usage status
349
+ const usedRules = processedRules.filter((rule) => rule.isUsed);
350
+ const unusedRules = processedRules.filter((rule) => !rule.isUsed);
351
+ return {
352
+ summary: {
353
+ totalRules: cssData.totalRules,
354
+ usedRules: usedRules.length,
355
+ unusedRules: unusedRules.length,
356
+ unusedPercentage: Math.round((unusedRules.length / cssData.totalRules) * 100),
357
+ detectedFrameworks: frameworks
358
+ },
359
+ usedRules,
360
+ unusedRules,
361
+ pageInfo: {
362
+ title: cssData.pageTitle,
363
+ url: cssData.pageUrl,
364
+ timestamp: urlData.timestamp
365
+ }
366
+ };
367
+ }
368
+ /**
369
+ * Process local CSS data using our parser utility
370
+ */
371
+ processLocalCSSData(cssContent, htmlContent, params) {
372
+ // Extract selectors using our CSS parser
373
+ const selectors = CssParser.extractSelectors(cssContent, params.cssPath || 'input');
374
+ const frameworks = CssParser.detectBasicFrameworks(cssContent);
375
+ const fileSizeKB = CssParser.getFileSizeKB(cssContent);
376
+ // If we have HTML content, check usage
377
+ let usedSelectors = [];
378
+ let unusedSelectors = [...selectors];
379
+ if (htmlContent) {
380
+ // Simple check for selector usage in HTML
381
+ selectors.forEach(sel => {
382
+ const selectorText = sel.selector;
383
+ // Basic usage detection (could be enhanced)
384
+ if (this.isSelectorUsedInHTML(selectorText, htmlContent, params.ignorePseudoSelectors)) {
385
+ usedSelectors.push(selectorText);
386
+ unusedSelectors = unusedSelectors.filter(u => u.selector !== selectorText);
387
+ }
388
+ });
389
+ }
390
+ return {
391
+ summary: {
392
+ totalSelectors: selectors.length,
393
+ usedSelectors: usedSelectors.length,
394
+ unusedSelectors: unusedSelectors.length,
395
+ unusedPercentage: htmlContent ? Math.round((unusedSelectors.length / selectors.length) * 100) : null,
396
+ fileSizeKB,
397
+ detectedFrameworks: frameworks,
398
+ includeMediaQueries: params.includeMediaQueries
399
+ },
400
+ allSelectors: selectors,
401
+ usedSelectors,
402
+ unusedSelectors,
403
+ hasHTML: !!htmlContent
404
+ };
405
+ }
406
+ /**
407
+ * Basic selector usage detection in HTML
408
+ */
409
+ isSelectorUsedInHTML(selector, html, ignorePseudo = false) {
410
+ // Remove pseudo-selectors if requested
411
+ if (ignorePseudo) {
412
+ selector = selector.replace(/:(hover|focus|active|visited|link|first-child|last-child|nth-child\([^)]+\))/g, '');
413
+ }
414
+ // Extract class and ID selectors for basic matching
415
+ const classMatches = selector.match(/\\.([a-zA-Z0-9_-]+)/g);
416
+ const idMatches = selector.match(/#([a-zA-Z0-9_-]+)/g);
417
+ const elementMatches = selector.match(/^[a-zA-Z][a-zA-Z0-9]*(?![.#])/);
418
+ // Check for class usage
419
+ if (classMatches) {
420
+ for (const classMatch of classMatches) {
421
+ const className = classMatch.substring(1); // Remove the dot
422
+ if (html.includes(`class="${className}"`) || html.includes(`class='${className}'`) ||
423
+ html.includes(`class="[^"]*${className}[^"]*"`) || html.includes(`class='[^']*${className}[^']*'`)) {
424
+ return true;
425
+ }
426
+ }
427
+ }
428
+ // Check for ID usage
429
+ if (idMatches) {
430
+ for (const idMatch of idMatches) {
431
+ const idName = idMatch.substring(1); // Remove the hash
432
+ if (html.includes(`id="${idName}"`) || html.includes(`id='${idName}'`)) {
433
+ return true;
434
+ }
435
+ }
436
+ }
437
+ // Check for element usage
438
+ if (elementMatches) {
439
+ const element = elementMatches[0];
440
+ if (html.includes(`<${element}`) || html.includes(`</${element}`)) {
441
+ return true;
442
+ }
443
+ }
444
+ return false;
445
+ }
446
+ /**
447
+ * URL analysis prompt stages
448
+ */
449
+ getURLAnalysisPromptStages(params) {
450
+ const { urlData, analysisDepth, analysisType } = params;
451
+ const systemAndContext = `You are an expert CSS performance analyst specializing in ${analysisDepth} ${analysisType} analysis of live websites.
452
+
453
+ Analysis Context:
454
+ - Analysis Type: ${analysisType}
455
+ - Analysis Depth: ${analysisDepth}
456
+ - Mode: Live URL Analysis
457
+ - URL: ${urlData.pageInfo.url}
458
+
459
+ Your Mission:
460
+ Analyze CSS usage patterns from a live website to identify performance optimization opportunities. Focus on unused selectors, CSS bloat, and optimization recommendations.
461
+
462
+ Your Expertise:
463
+ - CSS performance optimization and unused code detection
464
+ - Web performance analysis and Core Web Vitals impact
465
+ - Framework CSS analysis and cleanup strategies
466
+ - Cross-browser compatibility and selector efficiency
467
+ - CSS architecture and maintainability best practices
468
+
469
+ Analysis Methodology:
470
+ 1. Examine the CSS usage data extracted from the live page
471
+ 2. Identify genuinely unused selectors vs. dynamic/JS-dependent rules
472
+ 3. Assess performance impact and optimization opportunities
473
+ 4. Provide conservative recommendations that won't break functionality
474
+ 5. Consider framework patterns and common CSS practices`;
475
+ const dataPayload = `URL Analysis Data:
476
+
477
+ Page Information:
478
+ - Title: ${urlData.pageInfo.title}
479
+ - URL: ${urlData.pageInfo.url}
480
+ - Analysis Date: ${urlData.pageInfo.timestamp}
481
+
482
+ CSS Usage Summary:
483
+ - Total CSS Rules: ${urlData.summary.totalRules}
484
+ - Used Rules: ${urlData.summary.usedRules}
485
+ - Unused Rules: ${urlData.summary.unusedRules}
486
+ - Unused Percentage: ${urlData.summary.unusedPercentage}%
487
+ - Detected Frameworks: ${urlData.summary.detectedFrameworks.join(', ') || 'None detected'}
488
+
489
+ Unused CSS Rules (Sample):
490
+ ${JSON.stringify(urlData.unusedRules.slice(0, 20), null, 2)}
491
+
492
+ Used CSS Rules (Sample):
493
+ ${JSON.stringify(urlData.usedRules.slice(0, 10), null, 2)}
494
+
495
+ Note: Analysis based on current page state. Dynamic content and JavaScript interactions may affect actual usage.`;
496
+ const outputInstructions = `Provide comprehensive CSS usage analysis with the following structure:
497
+
498
+ ## Executive Summary
499
+ Provide an executive summary of CSS usage and optimization opportunities found during the analysis.
500
+
501
+ ## Unused CSS Analysis
502
+ - **Total Unused Rules**: Count and percentage of unused CSS rules
503
+ - **Categories**:
504
+ - **Safe to Remove**: Selectors that are definitely unused and can be safely removed
505
+ - **Requires Investigation**: Selectors that might be used by JavaScript or dynamic content
506
+ - **Framework Related**: Selectors from detected frameworks that may be conditionally used
507
+
508
+ ## Performance Impact Assessment
509
+ - **Estimated Savings**: Projected file size reduction from removing unused CSS
510
+ - **Load Time Impact**: Expected performance improvement in page loading
511
+ - **Core Web Vitals Impact**: How optimizations will affect CLS, LCP, and FID scores
512
+
513
+ ## Optimization Recommendations
514
+ For each recommendation, provide:
515
+ - **Action**: Specific optimization action to take
516
+ - **Impact Level**: High, medium, or low impact on performance
517
+ - **Implementation Effort**: Low, medium, or high effort required
518
+ - **Description**: Detailed explanation and implementation guidance
519
+
520
+ ## Framework-Specific Insights
521
+ - **Detected Frameworks**: List any CSS frameworks identified (Bootstrap, Tailwind, etc.)
522
+ - **Framework Advice**: Specific guidance for optimizing framework-related CSS
523
+
524
+ ## Important Warnings
525
+ List any critical considerations or warnings before making changes, especially regarding:
526
+ - Dynamic content that might use CSS classes at runtime
527
+ - Third-party integrations that may depend on specific CSS
528
+ - Mobile-specific or conditional styling
529
+
530
+ ## Confidence Assessment
531
+ Provide your confidence level in the analysis and any limitations of the static analysis approach.
532
+
533
+ **Focus on actionable recommendations that safely improve CSS performance without breaking functionality.**`;
534
+ return { systemAndContext, dataPayload, outputInstructions };
535
+ }
536
+ /**
537
+ * Single-file analysis prompt stages
538
+ */
539
+ getSingleFilePromptStages(params) {
540
+ const { processedData, analysisDepth, analysisType } = params;
541
+ const systemAndContext = `You are an expert CSS code analyst specializing in ${analysisDepth} ${analysisType} analysis of CSS files.
542
+
543
+ Analysis Context:
544
+ - Analysis Type: ${analysisType}
545
+ - Analysis Depth: ${analysisDepth}
546
+ - Mode: Local File Analysis
547
+ - Has HTML Reference: ${processedData.hasHTML}
548
+
549
+ Your Mission:
550
+ Analyze CSS file structure and usage patterns to identify optimization opportunities, unused selectors, and code quality issues.
551
+
552
+ Your Expertise:
553
+ - CSS architecture and organization best practices
554
+ - Selector efficiency and performance optimization
555
+ - CSS maintainability and code quality assessment
556
+ - Framework detection and optimization strategies
557
+ - Cross-file dependency analysis and cleanup
558
+
559
+ Analysis Methodology:
560
+ 1. Examine CSS structure and selector patterns
561
+ 2. Identify potential unused or redundant selectors
562
+ 3. Assess code organization and maintainability
563
+ 4. Provide optimization recommendations
564
+ 5. Consider framework patterns and modern CSS practices`;
565
+ const dataPayload = `CSS File Analysis Data:
566
+
567
+ Summary:
568
+ - Total Selectors: ${processedData.summary.totalSelectors}
569
+ - File Size: ${processedData.summary.fileSizeKB} KB
570
+ - Detected Frameworks: ${processedData.summary.detectedFrameworks.join(', ') || 'None detected'}
571
+ ${processedData.hasHTML ? `- Used Selectors: ${processedData.summary.usedSelectors}
572
+ - Unused Selectors: ${processedData.summary.unusedSelectors}
573
+ - Unused Percentage: ${processedData.summary.unusedPercentage}%` : '- HTML Reference: Not provided (usage analysis limited)'}
574
+
575
+ All Selectors:
576
+ ${JSON.stringify(processedData.allSelectors, null, 2)}
577
+
578
+ ${processedData.hasHTML ? `
579
+ Unused Selectors:
580
+ ${JSON.stringify(processedData.unusedSelectors, null, 2)}
581
+ ` : ''}`;
582
+ const outputInstructions = `Provide comprehensive CSS file analysis with the following structure:
583
+
584
+ **File Overview and Assessment**
585
+ Provide a comprehensive overview of CSS file structure, quality assessment, and organizational patterns identified during analysis.
586
+
587
+ **CSS File Structure Analysis**
588
+ - Detailed evaluation of CSS organization, architecture patterns, and structural quality
589
+ - Comprehensive assessment of code complexity, maintainability, and overall architectural approach
590
+ - Framework detection results with analysis of any detected frameworks and their usage patterns throughout the file
591
+
592
+ ${processedData.hasHTML ? `**CSS Usage Pattern Analysis**
593
+ - Detailed analysis of unused selectors with count, categorization, and optimization potential assessment
594
+ - Comprehensive evaluation of how selectors are used throughout the HTML with usage pattern insights
595
+ - Estimated potential savings from cleanup operations including file size reduction and performance impact
596
+
597
+ ` : ''}**Code Quality Issues and Findings**
598
+ For each issue identified during analysis:
599
+ - Clear categorization of the problem type with detailed classification
600
+ - Severity level assessment ranging from high impact to low priority issues
601
+ - Comprehensive detailed description explaining the nature and implications of each issue
602
+ - Specific affected selectors or CSS rules involved in the problematic patterns
603
+ - Step-by-step recommendation and implementation guidance for addressing each issue
604
+
605
+ **CSS Optimization Opportunities**
606
+ For each optimization suggestion discovered:
607
+ - Specific area for improvement with clear identification and scope
608
+ - Expected benefit analysis including what improvements can be realistically achieved
609
+ - Detailed implementation guide explaining exactly how to implement each optimization safely
610
+
611
+ **Priority Implementation Recommendations**
612
+ Comprehensive list of the most important recommendations for improving the CSS, carefully ordered by priority, implementation impact, and development effort required.
613
+
614
+ **Analysis Confidence and Limitations**
615
+ Professional assessment of confidence level in the analysis with clear explanation of any limitations, assumptions, or constraints in the assessment approach.
616
+
617
+ Focus on providing actionable insights that improve CSS maintainability, performance optimization, and overall code quality while ensuring recommendations are practical and implementable.`;
618
+ return { systemAndContext, dataPayload, outputInstructions };
619
+ }
620
+ /**
621
+ * Multi-file analysis prompt stages
622
+ */
623
+ getMultiFilePromptStages(params) {
624
+ const { analysisResult, analysisType, analysisDepth, fileCount } = params;
625
+ const systemAndContext = `You are an expert multi-file CSS analyst specializing in ${analysisDepth} ${analysisType} analysis across web projects.
626
+
627
+ Analysis Context:
628
+ - Analysis Type: ${analysisType}
629
+ - Analysis Depth: ${analysisDepth}
630
+ - Files Analyzed: ${fileCount}
631
+ - Mode: Multi-File Project Analysis
632
+
633
+ Your Mission:
634
+ Analyze CSS usage patterns across an entire web project to identify cross-file optimization opportunities, architectural issues, and comprehensive cleanup strategies.
635
+
636
+ Your Expertise:
637
+ - Project-wide CSS architecture and organization
638
+ - Cross-file CSS dependency analysis and optimization
639
+ - Multi-file unused code detection and cleanup strategies
640
+ - CSS performance optimization at project scale
641
+ - Framework integration and optimization across files
642
+
643
+ Analysis Methodology:
644
+ 1. Examine cross-file CSS patterns and dependencies
645
+ 2. Identify project-wide unused or redundant styles
646
+ 3. Assess overall CSS architecture and organization
647
+ 4. Provide comprehensive optimization strategy
648
+ 5. Consider build process and deployment optimization`;
649
+ const dataPayload = `Multi-File CSS Analysis Results:
650
+
651
+ ${JSON.stringify(analysisResult, null, 2)}`;
652
+ const outputInstructions = `Provide comprehensive multi-file CSS analysis with the following structure:
653
+
654
+ ## Overall Summary
655
+ Provide overall project CSS analysis and optimization potential across all analyzed files.
656
+
657
+ ## Project Analysis
658
+ - **Architecture Assessment**: Evaluation of project CSS organization and structure
659
+ - **Total Size Impact**: Combined CSS file sizes and their impact
660
+ - **Framework Detection**: List detected frameworks used across the project
661
+ - **Duplicate Pattern Analysis**: Identification of duplicate or redundant CSS across files
662
+
663
+ ## Cross-File Findings
664
+ For each cross-file issue identified:
665
+ - **Issue Type**: optimization, redundancy, or architecture concern
666
+ - **Severity Level**: High, medium, or low impact
667
+ - **Description**: Clear explanation of the cross-file issue
668
+ - **Affected Files**: Specific CSS files involved in the issue
669
+ - **Recommendation**: How to optimize or resolve across files
670
+
671
+ ## Optimization Strategy
672
+ - **Priority Order**: Recommended optimization sequence for maximum impact
673
+ - **Estimated Savings**: Project-wide optimization potential and expected benefits
674
+ - **Build Process Recommendations**: Suggestions for build-time optimizations
675
+
676
+ ## Priority Recommendations
677
+ List the most important project-wide recommendations for CSS optimization and cleanup.
678
+
679
+ ## Confidence Assessment
680
+ Provide confidence level in the cross-file analysis and note any limitations.
681
+
682
+ **Focus on actionable insights that improve CSS architecture, reduce duplication, and optimize the entire project's CSS performance.**`;
683
+ return { systemAndContext, dataPayload, outputInstructions };
684
+ }
685
+ /**
686
+ * Multi-file helper methods
687
+ */
688
+ async discoverRelevantFiles(projectPath, maxDepth, analysisType) {
689
+ const extensions = this.getFileExtensions(analysisType);
690
+ return await this.multiFileAnalysis.discoverFiles(projectPath, extensions, maxDepth);
691
+ }
692
+ async performMultiFileAnalysis(files, params, model, contextLength) {
693
+ const cacheKey = this.analysisCache.generateKey('find_unused_css', params, files);
694
+ const cached = await this.analysisCache.get(cacheKey);
695
+ if (cached)
696
+ return cached;
697
+ const fileAnalysisResults = await this.multiFileAnalysis.analyzeBatch(files, (file) => this.analyzeIndividualCSSFile(file, params, model), contextLength);
698
+ // Aggregate results
699
+ const aggregatedResult = {
700
+ summary: `Multi-file CSS analysis of ${files.length} files`,
701
+ files: fileAnalysisResults,
702
+ totalSizeKB: fileAnalysisResults.reduce((sum, result) => sum + (result.sizeKB || 0), 0),
703
+ totalSelectors: fileAnalysisResults.reduce((sum, result) => sum + (result.selectorCount || 0), 0),
704
+ combinedFrameworks: [...new Set(fileAnalysisResults.flatMap((result) => result.frameworks || []))]
705
+ };
706
+ await this.analysisCache.cacheAnalysis(cacheKey, aggregatedResult, {
707
+ modelUsed: model.identifier || 'unknown',
708
+ executionTime: Date.now(),
709
+ timestamp: new Date().toISOString()
710
+ });
711
+ return aggregatedResult;
712
+ }
713
+ async analyzeIndividualCSSFile(file, params, model) {
714
+ const content = await readFile(file, 'utf-8');
715
+ const selectors = CssParser.extractSelectors(content, file);
716
+ const frameworks = CssParser.detectBasicFrameworks(content);
717
+ const sizeKB = CssParser.getFileSizeKB(content);
718
+ return {
719
+ filePath: file,
720
+ fileName: basename(file),
721
+ sizeKB,
722
+ selectorCount: selectors.length,
723
+ frameworks,
724
+ relativePath: relative(params.projectPath || '', file),
725
+ selectors: selectors.slice(0, 10) // Sample for analysis
726
+ };
727
+ }
728
+ getFileExtensions(analysisType) {
729
+ const extensionMap = {
730
+ 'performance': ['.css', '.scss', '.sass', '.less'],
731
+ 'usage': ['.css', '.html', '.htm', '.php', '.jsx', '.tsx', '.vue'],
732
+ 'comprehensive': ['.css', '.scss', '.sass', '.less', '.html', '.htm', '.php', '.jsx', '.tsx', '.vue']
733
+ };
734
+ return extensionMap[analysisType] || extensionMap.comprehensive;
735
+ }
736
+ /**
737
+ * For backwards compatibility
738
+ */
739
+ getPromptStages(params) {
740
+ const mode = this.detectAnalysisMode(params);
741
+ if (mode === 'url') {
742
+ // This shouldn't be called for URL mode as it requires async processing
743
+ throw new Error('URL analysis requires async processing - use execute method');
744
+ }
745
+ else if (mode === 'single-file') {
746
+ return this.getSingleFilePromptStages(params);
747
+ }
748
+ else {
749
+ return this.getMultiFilePromptStages(params);
750
+ }
751
+ }
752
+ }
753
+ export default FindUnusedCSSAnalyzer;
754
+ //# sourceMappingURL=find-unused-css.js.map