claude-mpm 4.2.44__py3-none-any.whl → 4.2.51__py3-none-any.whl
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.
- claude_mpm/VERSION +1 -1
- claude_mpm/agents/BASE_PM.md +43 -1
- claude_mpm/agents/INSTRUCTIONS.md +75 -1
- claude_mpm/agents/WORKFLOW.md +46 -1
- claude_mpm/agents/frontmatter_validator.py +20 -12
- claude_mpm/agents/templates/nextjs_engineer.json +277 -0
- claude_mpm/agents/templates/python_engineer.json +289 -0
- claude_mpm/agents/templates/react_engineer.json +11 -3
- claude_mpm/agents/templates/security.json +50 -9
- claude_mpm/cli/commands/agents.py +2 -2
- claude_mpm/cli/commands/uninstall.py +1 -2
- claude_mpm/cli/interactive/agent_wizard.py +3 -3
- claude_mpm/cli/parsers/agent_manager_parser.py +3 -3
- claude_mpm/cli/parsers/agents_parser.py +1 -1
- claude_mpm/constants.py +1 -1
- claude_mpm/core/error_handler.py +2 -4
- claude_mpm/core/file_utils.py +4 -12
- claude_mpm/core/log_manager.py +8 -5
- claude_mpm/core/logger.py +1 -1
- claude_mpm/core/logging_utils.py +6 -6
- claude_mpm/core/unified_agent_registry.py +18 -4
- claude_mpm/dashboard/react/components/DataInspector/DataInspector.module.css +188 -0
- claude_mpm/dashboard/react/components/EventViewer/EventViewer.module.css +156 -0
- claude_mpm/dashboard/react/components/shared/ConnectionStatus.module.css +38 -0
- claude_mpm/dashboard/react/components/shared/FilterBar.module.css +92 -0
- claude_mpm/dashboard/static/archive/activity_dashboard_fixed.html +248 -0
- claude_mpm/dashboard/static/archive/activity_dashboard_test.html +61 -0
- claude_mpm/dashboard/static/archive/test_activity_connection.html +179 -0
- claude_mpm/dashboard/static/archive/test_claude_tree_tab.html +68 -0
- claude_mpm/dashboard/static/archive/test_dashboard.html +409 -0
- claude_mpm/dashboard/static/archive/test_dashboard_fixed.html +519 -0
- claude_mpm/dashboard/static/archive/test_dashboard_verification.html +181 -0
- claude_mpm/dashboard/static/archive/test_file_data.html +315 -0
- claude_mpm/dashboard/static/archive/test_file_tree_empty_state.html +243 -0
- claude_mpm/dashboard/static/archive/test_file_tree_fix.html +234 -0
- claude_mpm/dashboard/static/archive/test_file_tree_rename.html +117 -0
- claude_mpm/dashboard/static/archive/test_file_tree_tab.html +115 -0
- claude_mpm/dashboard/static/archive/test_file_viewer.html +224 -0
- claude_mpm/dashboard/static/archive/test_final_activity.html +220 -0
- claude_mpm/dashboard/static/archive/test_tab_fix.html +139 -0
- claude_mpm/dashboard/static/built/assets/events.DjpNxWNo.css +1 -0
- claude_mpm/dashboard/static/built/components/activity-tree.js +1 -1
- claude_mpm/dashboard/static/built/components/agent-hierarchy.js +777 -0
- claude_mpm/dashboard/static/built/components/agent-inference.js +1 -1
- claude_mpm/dashboard/static/built/components/build-tracker.js +333 -0
- claude_mpm/dashboard/static/built/components/code-simple.js +857 -0
- claude_mpm/dashboard/static/built/components/code-tree/tree-breadcrumb.js +353 -0
- claude_mpm/dashboard/static/built/components/code-tree/tree-constants.js +235 -0
- claude_mpm/dashboard/static/built/components/code-tree/tree-search.js +409 -0
- claude_mpm/dashboard/static/built/components/code-tree/tree-utils.js +435 -0
- claude_mpm/dashboard/static/built/components/code-viewer.js +2 -1076
- claude_mpm/dashboard/static/built/components/connection-debug.js +654 -0
- claude_mpm/dashboard/static/built/components/diff-viewer.js +891 -0
- claude_mpm/dashboard/static/built/components/event-processor.js +1 -1
- claude_mpm/dashboard/static/built/components/event-viewer.js +1 -1
- claude_mpm/dashboard/static/built/components/export-manager.js +1 -1
- claude_mpm/dashboard/static/built/components/file-change-tracker.js +443 -0
- claude_mpm/dashboard/static/built/components/file-change-viewer.js +690 -0
- claude_mpm/dashboard/static/built/components/file-tool-tracker.js +1 -1
- claude_mpm/dashboard/static/built/components/module-viewer.js +1 -1
- claude_mpm/dashboard/static/built/components/nav-bar.js +145 -0
- claude_mpm/dashboard/static/built/components/page-structure.js +429 -0
- claude_mpm/dashboard/static/built/components/session-manager.js +1 -1
- claude_mpm/dashboard/static/built/components/ui-state-manager.js +2 -465
- claude_mpm/dashboard/static/built/components/working-directory.js +1 -1
- claude_mpm/dashboard/static/built/connection-manager.js +536 -0
- claude_mpm/dashboard/static/built/dashboard.js +1 -1
- claude_mpm/dashboard/static/built/extension-error-handler.js +164 -0
- claude_mpm/dashboard/static/built/react/events.js +30 -0
- claude_mpm/dashboard/static/built/shared/dom-helpers.js +396 -0
- claude_mpm/dashboard/static/built/shared/event-bus.js +330 -0
- claude_mpm/dashboard/static/built/shared/event-filter-service.js +540 -0
- claude_mpm/dashboard/static/built/shared/logger.js +385 -0
- claude_mpm/dashboard/static/built/shared/page-structure.js +251 -0
- claude_mpm/dashboard/static/built/shared/tooltip-service.js +253 -0
- claude_mpm/dashboard/static/built/socket-client.js +1 -1
- claude_mpm/dashboard/static/built/tab-isolation-fix.js +185 -0
- claude_mpm/dashboard/static/css/dashboard.css +28 -5
- claude_mpm/dashboard/static/dist/assets/events.DjpNxWNo.css +1 -0
- claude_mpm/dashboard/static/dist/components/activity-tree.js +1 -1
- claude_mpm/dashboard/static/dist/components/agent-inference.js +1 -1
- claude_mpm/dashboard/static/dist/components/code-viewer.js +2 -0
- claude_mpm/dashboard/static/dist/components/event-processor.js +1 -1
- claude_mpm/dashboard/static/dist/components/event-viewer.js +1 -1
- claude_mpm/dashboard/static/dist/components/export-manager.js +1 -1
- claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +1 -1
- claude_mpm/dashboard/static/dist/components/module-viewer.js +1 -1
- claude_mpm/dashboard/static/dist/components/session-manager.js +1 -1
- claude_mpm/dashboard/static/dist/components/working-directory.js +1 -1
- claude_mpm/dashboard/static/dist/dashboard.js +1 -1
- claude_mpm/dashboard/static/dist/react/events.js +30 -0
- claude_mpm/dashboard/static/dist/socket-client.js +1 -1
- claude_mpm/dashboard/static/events.html +607 -0
- claude_mpm/dashboard/static/index.html +713 -0
- claude_mpm/dashboard/static/js/components/activity-tree.js +3 -17
- claude_mpm/dashboard/static/js/components/agent-hierarchy.js +4 -1
- claude_mpm/dashboard/static/js/components/agent-inference.js +3 -0
- claude_mpm/dashboard/static/js/components/build-tracker.js +8 -0
- claude_mpm/dashboard/static/js/components/code-viewer.js +306 -66
- claude_mpm/dashboard/static/js/components/event-processor.js +3 -0
- claude_mpm/dashboard/static/js/components/event-viewer.js +39 -2
- claude_mpm/dashboard/static/js/components/export-manager.js +3 -0
- claude_mpm/dashboard/static/js/components/file-tool-tracker.js +30 -10
- claude_mpm/dashboard/static/js/components/socket-manager.js +4 -0
- claude_mpm/dashboard/static/js/components/ui-state-manager.js +285 -85
- claude_mpm/dashboard/static/js/components/working-directory.js +3 -0
- claude_mpm/dashboard/static/js/dashboard.js +61 -33
- claude_mpm/dashboard/static/js/socket-client.js +12 -8
- claude_mpm/dashboard/static/js/stores/dashboard-store.js +562 -0
- claude_mpm/dashboard/static/js/tab-isolation-fix.js +185 -0
- claude_mpm/dashboard/static/legacy/activity.html +736 -0
- claude_mpm/dashboard/static/legacy/agents.html +786 -0
- claude_mpm/dashboard/static/legacy/files.html +747 -0
- claude_mpm/dashboard/static/legacy/tools.html +831 -0
- claude_mpm/dashboard/static/monitors-index.html +218 -0
- claude_mpm/dashboard/static/monitors.html +431 -0
- claude_mpm/dashboard/static/production/events.html +659 -0
- claude_mpm/dashboard/static/production/main.html +715 -0
- claude_mpm/dashboard/static/production/monitors.html +483 -0
- claude_mpm/dashboard/static/socket.io.min.js +7 -0
- claude_mpm/dashboard/static/socket.io.v4.8.1.backup.js +7 -0
- claude_mpm/dashboard/static/test-archive/dashboard.html +635 -0
- claude_mpm/dashboard/static/test-archive/debug-events.html +147 -0
- claude_mpm/dashboard/static/test-archive/test-navigation.html +256 -0
- claude_mpm/dashboard/static/test-archive/test-react-exports.html +180 -0
- claude_mpm/dashboard/templates/index.html +79 -9
- claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +1 -1
- claude_mpm/services/agents/deployment/agent_discovery_service.py +3 -0
- claude_mpm/services/agents/deployment/agent_template_builder.py +25 -8
- claude_mpm/services/agents/deployment/agent_validator.py +3 -0
- claude_mpm/services/agents/deployment/validation/template_validator.py +13 -4
- claude_mpm/services/agents/local_template_manager.py +2 -6
- claude_mpm/services/monitor/daemon.py +1 -2
- claude_mpm/services/monitor/daemon_manager.py +2 -5
- claude_mpm/services/monitor/event_emitter.py +2 -2
- claude_mpm/services/monitor/handlers/code_analysis.py +4 -6
- claude_mpm/services/monitor/handlers/hooks.py +2 -4
- claude_mpm/services/monitor/server.py +27 -4
- claude_mpm/tools/code_tree_analyzer.py +2 -2
- {claude_mpm-4.2.44.dist-info → claude_mpm-4.2.51.dist-info}/METADATA +1 -1
- {claude_mpm-4.2.44.dist-info → claude_mpm-4.2.51.dist-info}/RECORD +146 -81
- claude_mpm/dashboard/static/test-browser-monitor.html +0 -470
- claude_mpm/dashboard/static/test-simple.html +0 -97
- /claude_mpm/dashboard/static/{test_debug.html → test-archive/test_debug.html} +0 -0
- {claude_mpm-4.2.44.dist-info → claude_mpm-4.2.51.dist-info}/WHEEL +0 -0
- {claude_mpm-4.2.44.dist-info → claude_mpm-4.2.51.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.2.44.dist-info → claude_mpm-4.2.51.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.2.44.dist-info → claude_mpm-4.2.51.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,409 @@
|
|
1
|
+
/**
|
2
|
+
* Tree Search Functionality
|
3
|
+
*
|
4
|
+
* Search and filter functionality for the code tree visualization.
|
5
|
+
* Provides searching, filtering, and highlighting capabilities.
|
6
|
+
*
|
7
|
+
* @module tree-search
|
8
|
+
*/
|
9
|
+
|
10
|
+
class TreeSearch {
|
11
|
+
constructor() {
|
12
|
+
this.searchTerm = '';
|
13
|
+
this.languageFilter = 'all';
|
14
|
+
this.complexityFilter = { min: 0, max: 999 };
|
15
|
+
this.typeFilter = 'all';
|
16
|
+
this.searchHistory = [];
|
17
|
+
this.maxHistorySize = 20;
|
18
|
+
this.debounceTimer = null;
|
19
|
+
this.debounceDelay = 300;
|
20
|
+
}
|
21
|
+
|
22
|
+
/**
|
23
|
+
* Set search term with optional debouncing
|
24
|
+
* @param {string} term - Search term
|
25
|
+
* @param {Function} callback - Callback to execute after debounce
|
26
|
+
* @param {boolean} immediate - Execute immediately without debounce
|
27
|
+
*/
|
28
|
+
setSearchTerm(term, callback, immediate = false) {
|
29
|
+
this.searchTerm = term.toLowerCase();
|
30
|
+
|
31
|
+
if (callback) {
|
32
|
+
if (immediate) {
|
33
|
+
callback(this.searchTerm);
|
34
|
+
} else {
|
35
|
+
this.debounce(() => callback(this.searchTerm), this.debounceDelay);
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
39
|
+
// Add to history if not empty and not duplicate
|
40
|
+
if (term && this.searchHistory[0] !== term) {
|
41
|
+
this.searchHistory.unshift(term);
|
42
|
+
if (this.searchHistory.length > this.maxHistorySize) {
|
43
|
+
this.searchHistory.pop();
|
44
|
+
}
|
45
|
+
}
|
46
|
+
}
|
47
|
+
|
48
|
+
/**
|
49
|
+
* Set language filter
|
50
|
+
* @param {string} language - Language to filter by
|
51
|
+
*/
|
52
|
+
setLanguageFilter(language) {
|
53
|
+
this.languageFilter = language;
|
54
|
+
}
|
55
|
+
|
56
|
+
/**
|
57
|
+
* Set complexity filter
|
58
|
+
* @param {number} min - Minimum complexity
|
59
|
+
* @param {number} max - Maximum complexity
|
60
|
+
*/
|
61
|
+
setComplexityFilter(min, max) {
|
62
|
+
this.complexityFilter = { min, max };
|
63
|
+
}
|
64
|
+
|
65
|
+
/**
|
66
|
+
* Set type filter
|
67
|
+
* @param {string} type - Node type to filter by
|
68
|
+
*/
|
69
|
+
setTypeFilter(type) {
|
70
|
+
this.typeFilter = type;
|
71
|
+
}
|
72
|
+
|
73
|
+
/**
|
74
|
+
* Filter tree nodes based on current criteria
|
75
|
+
* @param {Object} root - Root node of the tree
|
76
|
+
* @returns {Object} Filtered tree structure
|
77
|
+
*/
|
78
|
+
filterTree(root) {
|
79
|
+
if (!root) return null;
|
80
|
+
|
81
|
+
// Mark all nodes as visible initially
|
82
|
+
this.resetNodeVisibility(root);
|
83
|
+
|
84
|
+
// Apply filters
|
85
|
+
root.descendants().forEach(node => {
|
86
|
+
const shouldHide = !this.nodeMatchesFilters(node);
|
87
|
+
node.data._hidden = shouldHide;
|
88
|
+
|
89
|
+
// Mark node for search highlighting
|
90
|
+
if (this.searchTerm && !shouldHide) {
|
91
|
+
node.data._highlighted = this.nodeMatchesSearch(node);
|
92
|
+
} else {
|
93
|
+
node.data._highlighted = false;
|
94
|
+
}
|
95
|
+
});
|
96
|
+
|
97
|
+
// Ensure parent nodes are visible if any child is visible
|
98
|
+
this.ensureParentVisibility(root);
|
99
|
+
|
100
|
+
return root;
|
101
|
+
}
|
102
|
+
|
103
|
+
/**
|
104
|
+
* Check if node matches all active filters
|
105
|
+
* @param {Object} node - Node to check
|
106
|
+
* @returns {boolean} True if node matches all filters
|
107
|
+
*/
|
108
|
+
nodeMatchesFilters(node) {
|
109
|
+
// Language filter
|
110
|
+
if (!this.matchesLanguageFilter(node)) {
|
111
|
+
return false;
|
112
|
+
}
|
113
|
+
|
114
|
+
// Search term filter
|
115
|
+
if (!this.matchesSearchTerm(node)) {
|
116
|
+
return false;
|
117
|
+
}
|
118
|
+
|
119
|
+
// Complexity filter
|
120
|
+
if (!this.matchesComplexityFilter(node)) {
|
121
|
+
return false;
|
122
|
+
}
|
123
|
+
|
124
|
+
// Type filter
|
125
|
+
if (!this.matchesTypeFilter(node)) {
|
126
|
+
return false;
|
127
|
+
}
|
128
|
+
|
129
|
+
return true;
|
130
|
+
}
|
131
|
+
|
132
|
+
/**
|
133
|
+
* Check if node matches language filter
|
134
|
+
* @param {Object} node - Node to check
|
135
|
+
* @returns {boolean} True if matches
|
136
|
+
*/
|
137
|
+
matchesLanguageFilter(node) {
|
138
|
+
if (this.languageFilter === 'all') {
|
139
|
+
return true;
|
140
|
+
}
|
141
|
+
|
142
|
+
// Check node language
|
143
|
+
if (node.data.language === this.languageFilter) {
|
144
|
+
return true;
|
145
|
+
}
|
146
|
+
|
147
|
+
// Check if any children match (for directories)
|
148
|
+
if (node.children || node._children) {
|
149
|
+
const children = node.children || node._children;
|
150
|
+
return children.some(child => this.matchesLanguageFilter(child));
|
151
|
+
}
|
152
|
+
|
153
|
+
return false;
|
154
|
+
}
|
155
|
+
|
156
|
+
/**
|
157
|
+
* Check if node matches search term
|
158
|
+
* @param {Object} node - Node to check
|
159
|
+
* @returns {boolean} True if matches
|
160
|
+
*/
|
161
|
+
matchesSearchTerm(node) {
|
162
|
+
if (!this.searchTerm) {
|
163
|
+
return true;
|
164
|
+
}
|
165
|
+
|
166
|
+
// Check node name
|
167
|
+
if (node.data.name && node.data.name.toLowerCase().includes(this.searchTerm)) {
|
168
|
+
return true;
|
169
|
+
}
|
170
|
+
|
171
|
+
// Check node path
|
172
|
+
if (node.data.path && node.data.path.toLowerCase().includes(this.searchTerm)) {
|
173
|
+
return true;
|
174
|
+
}
|
175
|
+
|
176
|
+
// Check if any children match (for directories)
|
177
|
+
if (node.children || node._children) {
|
178
|
+
const children = node.children || node._children;
|
179
|
+
return children.some(child => this.matchesSearchTerm(child));
|
180
|
+
}
|
181
|
+
|
182
|
+
return false;
|
183
|
+
}
|
184
|
+
|
185
|
+
/**
|
186
|
+
* Check if node matches complexity filter
|
187
|
+
* @param {Object} node - Node to check
|
188
|
+
* @returns {boolean} True if matches
|
189
|
+
*/
|
190
|
+
matchesComplexityFilter(node) {
|
191
|
+
if (node.data.complexity === undefined) {
|
192
|
+
return true; // No complexity data, show by default
|
193
|
+
}
|
194
|
+
|
195
|
+
return node.data.complexity >= this.complexityFilter.min &&
|
196
|
+
node.data.complexity <= this.complexityFilter.max;
|
197
|
+
}
|
198
|
+
|
199
|
+
/**
|
200
|
+
* Check if node matches type filter
|
201
|
+
* @param {Object} node - Node to check
|
202
|
+
* @returns {boolean} True if matches
|
203
|
+
*/
|
204
|
+
matchesTypeFilter(node) {
|
205
|
+
if (this.typeFilter === 'all') {
|
206
|
+
return true;
|
207
|
+
}
|
208
|
+
|
209
|
+
return node.data.type === this.typeFilter;
|
210
|
+
}
|
211
|
+
|
212
|
+
/**
|
213
|
+
* Check if node matches search (for highlighting)
|
214
|
+
* @param {Object} node - Node to check
|
215
|
+
* @returns {boolean} True if node should be highlighted
|
216
|
+
*/
|
217
|
+
nodeMatchesSearch(node) {
|
218
|
+
if (!this.searchTerm) {
|
219
|
+
return false;
|
220
|
+
}
|
221
|
+
|
222
|
+
const name = (node.data.name || '').toLowerCase();
|
223
|
+
return name.includes(this.searchTerm);
|
224
|
+
}
|
225
|
+
|
226
|
+
/**
|
227
|
+
* Reset visibility flags on all nodes
|
228
|
+
* @param {Object} root - Root node
|
229
|
+
*/
|
230
|
+
resetNodeVisibility(root) {
|
231
|
+
if (!root) return;
|
232
|
+
|
233
|
+
root.descendants().forEach(node => {
|
234
|
+
node.data._hidden = false;
|
235
|
+
node.data._highlighted = false;
|
236
|
+
});
|
237
|
+
}
|
238
|
+
|
239
|
+
/**
|
240
|
+
* Ensure parent nodes are visible if any child is visible
|
241
|
+
* @param {Object} root - Root node
|
242
|
+
*/
|
243
|
+
ensureParentVisibility(root) {
|
244
|
+
// Bottom-up traversal to ensure parents are visible
|
245
|
+
const checkVisibility = (node) => {
|
246
|
+
if (node.children) {
|
247
|
+
let hasVisibleChild = false;
|
248
|
+
|
249
|
+
node.children.forEach(child => {
|
250
|
+
checkVisibility(child);
|
251
|
+
if (!child.data._hidden) {
|
252
|
+
hasVisibleChild = true;
|
253
|
+
}
|
254
|
+
});
|
255
|
+
|
256
|
+
// If node has visible children, it must be visible too
|
257
|
+
if (hasVisibleChild && node.data._hidden) {
|
258
|
+
node.data._hidden = false;
|
259
|
+
}
|
260
|
+
}
|
261
|
+
};
|
262
|
+
|
263
|
+
checkVisibility(root);
|
264
|
+
}
|
265
|
+
|
266
|
+
/**
|
267
|
+
* Search for nodes by path pattern
|
268
|
+
* @param {Object} root - Root node
|
269
|
+
* @param {string} pattern - Path pattern (supports wildcards)
|
270
|
+
* @returns {Array} Matching nodes
|
271
|
+
*/
|
272
|
+
searchByPath(root, pattern) {
|
273
|
+
if (!root || !pattern) return [];
|
274
|
+
|
275
|
+
const results = [];
|
276
|
+
const regexPattern = this.pathPatternToRegex(pattern);
|
277
|
+
|
278
|
+
root.descendants().forEach(node => {
|
279
|
+
if (node.data.path && regexPattern.test(node.data.path)) {
|
280
|
+
results.push(node);
|
281
|
+
}
|
282
|
+
});
|
283
|
+
|
284
|
+
return results;
|
285
|
+
}
|
286
|
+
|
287
|
+
/**
|
288
|
+
* Convert path pattern to regex
|
289
|
+
* @param {string} pattern - Path pattern with wildcards
|
290
|
+
* @returns {RegExp} Regular expression
|
291
|
+
*/
|
292
|
+
pathPatternToRegex(pattern) {
|
293
|
+
// Escape special regex characters except * and ?
|
294
|
+
const escaped = pattern.replace(/[.+^${}()|[\]\\]/g, '\\$&');
|
295
|
+
// Replace wildcards
|
296
|
+
const regexStr = escaped
|
297
|
+
.replace(/\*/g, '.*') // * matches any characters
|
298
|
+
.replace(/\?/g, '.'); // ? matches single character
|
299
|
+
|
300
|
+
return new RegExp('^' + regexStr + '$', 'i');
|
301
|
+
}
|
302
|
+
|
303
|
+
/**
|
304
|
+
* Get search suggestions based on current tree
|
305
|
+
* @param {Object} root - Root node
|
306
|
+
* @param {string} prefix - Search prefix
|
307
|
+
* @returns {Array} Suggested search terms
|
308
|
+
*/
|
309
|
+
getSearchSuggestions(root, prefix = '') {
|
310
|
+
if (!root) return [];
|
311
|
+
|
312
|
+
const suggestions = new Set();
|
313
|
+
const lowerPrefix = prefix.toLowerCase();
|
314
|
+
|
315
|
+
root.descendants().forEach(node => {
|
316
|
+
if (node.data.name) {
|
317
|
+
const name = node.data.name.toLowerCase();
|
318
|
+
if (name.startsWith(lowerPrefix)) {
|
319
|
+
suggestions.add(node.data.name);
|
320
|
+
}
|
321
|
+
}
|
322
|
+
});
|
323
|
+
|
324
|
+
return Array.from(suggestions).sort().slice(0, 10);
|
325
|
+
}
|
326
|
+
|
327
|
+
/**
|
328
|
+
* Highlight search results in node labels
|
329
|
+
* @param {string} text - Text to highlight
|
330
|
+
* @param {string} term - Search term
|
331
|
+
* @returns {string} HTML with highlighted term
|
332
|
+
*/
|
333
|
+
highlightSearchTerm(text, term = null) {
|
334
|
+
const searchTerm = term || this.searchTerm;
|
335
|
+
|
336
|
+
if (!searchTerm || !text) {
|
337
|
+
return text;
|
338
|
+
}
|
339
|
+
|
340
|
+
const regex = new RegExp(`(${this.escapeRegex(searchTerm)})`, 'gi');
|
341
|
+
return text.replace(regex, '<mark>$1</mark>');
|
342
|
+
}
|
343
|
+
|
344
|
+
/**
|
345
|
+
* Clear all filters
|
346
|
+
*/
|
347
|
+
clearFilters() {
|
348
|
+
this.searchTerm = '';
|
349
|
+
this.languageFilter = 'all';
|
350
|
+
this.complexityFilter = { min: 0, max: 999 };
|
351
|
+
this.typeFilter = 'all';
|
352
|
+
}
|
353
|
+
|
354
|
+
/**
|
355
|
+
* Get current filter summary
|
356
|
+
* @returns {string} Human-readable filter summary
|
357
|
+
*/
|
358
|
+
getFilterSummary() {
|
359
|
+
const parts = [];
|
360
|
+
|
361
|
+
if (this.searchTerm) {
|
362
|
+
parts.push(`Search: "${this.searchTerm}"`);
|
363
|
+
}
|
364
|
+
if (this.languageFilter !== 'all') {
|
365
|
+
parts.push(`Language: ${this.languageFilter}`);
|
366
|
+
}
|
367
|
+
if (this.typeFilter !== 'all') {
|
368
|
+
parts.push(`Type: ${this.typeFilter}`);
|
369
|
+
}
|
370
|
+
if (this.complexityFilter.min > 0 || this.complexityFilter.max < 999) {
|
371
|
+
parts.push(`Complexity: ${this.complexityFilter.min}-${this.complexityFilter.max}`);
|
372
|
+
}
|
373
|
+
|
374
|
+
return parts.length > 0 ? parts.join(', ') : 'No filters applied';
|
375
|
+
}
|
376
|
+
|
377
|
+
/**
|
378
|
+
* Debounce function calls
|
379
|
+
* @private
|
380
|
+
* @param {Function} func - Function to debounce
|
381
|
+
* @param {number} delay - Delay in milliseconds
|
382
|
+
*/
|
383
|
+
debounce(func, delay) {
|
384
|
+
clearTimeout(this.debounceTimer);
|
385
|
+
this.debounceTimer = setTimeout(func, delay);
|
386
|
+
}
|
387
|
+
|
388
|
+
/**
|
389
|
+
* Escape regex special characters
|
390
|
+
* @private
|
391
|
+
* @param {string} str - String to escape
|
392
|
+
* @returns {string} Escaped string
|
393
|
+
*/
|
394
|
+
escapeRegex(str) {
|
395
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
396
|
+
}
|
397
|
+
}
|
398
|
+
|
399
|
+
// Export as singleton for consistent state
|
400
|
+
const treeSearch = new TreeSearch();
|
401
|
+
|
402
|
+
// Support both module and global usage
|
403
|
+
if (typeof module !== 'undefined' && module.exports) {
|
404
|
+
module.exports = treeSearch;
|
405
|
+
} else if (typeof define === 'function' && define.amd) {
|
406
|
+
define([], () => treeSearch);
|
407
|
+
} else {
|
408
|
+
window.treeSearch = treeSearch;
|
409
|
+
}
|