agentgui 1.0.274 → 1.0.275
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +280 -280
- package/IPFS_DOWNLOADER.md +277 -277
- package/TASK_2C_COMPLETION.md +334 -334
- package/bin/gmgui.cjs +54 -54
- package/build-portable.js +3 -42
- package/database.js +1422 -1406
- package/lib/claude-runner.js +1130 -1130
- package/lib/ipfs-downloader.js +459 -459
- package/lib/speech.js +152 -152
- package/package.json +1 -1
- package/readme.md +76 -76
- package/server.js +3787 -3794
- package/setup-npm-token.sh +68 -68
- package/static/app.js +773 -773
- package/static/event-rendering-showcase.html +708 -708
- package/static/index.html +3178 -3180
- package/static/js/agent-auth.js +298 -298
- package/static/js/audio-recorder-processor.js +18 -18
- package/static/js/client.js +2656 -2656
- package/static/js/conversations.js +583 -583
- package/static/js/dialogs.js +267 -267
- package/static/js/event-consolidator.js +101 -101
- package/static/js/event-filter.js +311 -311
- package/static/js/event-processor.js +452 -452
- package/static/js/features.js +413 -413
- package/static/js/kalman-filter.js +67 -67
- package/static/js/progress-dialog.js +130 -130
- package/static/js/script-runner.js +219 -219
- package/static/js/streaming-renderer.js +2123 -2120
- package/static/js/syntax-highlighter.js +269 -269
- package/static/js/tts-websocket-handler.js +152 -152
- package/static/js/ui-components.js +431 -431
- package/static/js/voice.js +849 -849
- package/static/js/websocket-manager.js +596 -596
- package/static/templates/INDEX.html +465 -465
- package/static/templates/README.md +190 -190
- package/static/templates/agent-capabilities.html +56 -56
- package/static/templates/agent-metadata-panel.html +44 -44
- package/static/templates/agent-status-badge.html +30 -30
- package/static/templates/code-annotation-panel.html +155 -155
- package/static/templates/code-suggestion-panel.html +184 -184
- package/static/templates/command-header.html +77 -77
- package/static/templates/command-output-scrollable.html +118 -118
- package/static/templates/elapsed-time.html +54 -54
- package/static/templates/error-alert.html +106 -106
- package/static/templates/error-history-timeline.html +160 -160
- package/static/templates/error-recovery-options.html +109 -109
- package/static/templates/error-stack-trace.html +95 -95
- package/static/templates/error-summary.html +80 -80
- package/static/templates/event-counter.html +48 -48
- package/static/templates/execution-actions.html +97 -97
- package/static/templates/execution-progress-bar.html +80 -80
- package/static/templates/execution-stepper.html +120 -120
- package/static/templates/file-breadcrumb.html +118 -118
- package/static/templates/file-diff-viewer.html +121 -121
- package/static/templates/file-metadata.html +133 -133
- package/static/templates/file-read-panel.html +66 -66
- package/static/templates/file-write-panel.html +120 -120
- package/static/templates/git-branch-remote.html +107 -107
- package/static/templates/git-diff-list.html +101 -101
- package/static/templates/git-log-visualization.html +153 -153
- package/static/templates/git-status-panel.html +115 -115
- package/static/templates/quality-metrics-display.html +170 -170
- package/static/templates/terminal-output-panel.html +87 -87
- package/static/templates/test-results-display.html +144 -144
- package/static/theme.js +72 -72
- package/test-download-progress.js +223 -223
- package/test-websocket-broadcast.js +147 -147
- package/tests/ipfs-downloader.test.js +370 -370
|
@@ -1,269 +1,269 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Syntax Highlighter Integration
|
|
3
|
-
* Handles lazy-loading and caching of Prism.js for code highlighting
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
class SyntaxHighlighter {
|
|
7
|
-
constructor(config = {}) {
|
|
8
|
-
this.config = {
|
|
9
|
-
cdnUrl: config.cdnUrl || 'https://cdn.jsdelivr.net/npm/prismjs@1.29.0',
|
|
10
|
-
lazyLoad: config.lazyLoad !== false,
|
|
11
|
-
enableCache: config.enableCache !== false,
|
|
12
|
-
maxCacheSize: config.maxCacheSize || 500,
|
|
13
|
-
supportedLanguages: config.supportedLanguages || [
|
|
14
|
-
'javascript', 'typescript', 'python', 'java', 'cpp', 'c', 'csharp', 'go', 'rust',
|
|
15
|
-
'php', 'ruby', 'swift', 'kotlin', 'sql', 'html', 'css', 'scss', 'bash', 'shell',
|
|
16
|
-
'json', 'xml', 'yaml', 'markdown', 'plaintext'
|
|
17
|
-
],
|
|
18
|
-
...config
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
this.isLoaded = false;
|
|
22
|
-
this.isLoading = false;
|
|
23
|
-
this.highlightCache = new Map();
|
|
24
|
-
this.loadPromise = null;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Ensure Prism is loaded
|
|
29
|
-
*/
|
|
30
|
-
async ensureLoaded() {
|
|
31
|
-
// Already loaded
|
|
32
|
-
if (typeof Prism !== 'undefined' && this.isLoaded) {
|
|
33
|
-
return true;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// Currently loading
|
|
37
|
-
if (this.isLoading && this.loadPromise) {
|
|
38
|
-
return this.loadPromise;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// Start loading
|
|
42
|
-
this.isLoading = true;
|
|
43
|
-
this.loadPromise = this.loadPrism();
|
|
44
|
-
|
|
45
|
-
try {
|
|
46
|
-
const result = await this.loadPromise;
|
|
47
|
-
this.isLoaded = true;
|
|
48
|
-
return result;
|
|
49
|
-
} catch (error) {
|
|
50
|
-
console.error('Failed to load Prism:', error);
|
|
51
|
-
this.isLoading = false;
|
|
52
|
-
throw error;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Load Prism library
|
|
58
|
-
*/
|
|
59
|
-
async loadPrism() {
|
|
60
|
-
return new Promise((resolve, reject) => {
|
|
61
|
-
try {
|
|
62
|
-
// Load main Prism JS
|
|
63
|
-
const script = document.createElement('script');
|
|
64
|
-
script.src = `${this.config.cdnUrl}/prism.js`;
|
|
65
|
-
script.async = true;
|
|
66
|
-
|
|
67
|
-
script.onload = () => {
|
|
68
|
-
// Load common language files
|
|
69
|
-
this.loadLanguages();
|
|
70
|
-
this.isLoading = false;
|
|
71
|
-
resolve(true);
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
script.onerror = () => {
|
|
75
|
-
this.isLoading = false;
|
|
76
|
-
reject(new Error('Failed to load Prism.js'));
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
document.head.appendChild(script);
|
|
80
|
-
} catch (error) {
|
|
81
|
-
this.isLoading = false;
|
|
82
|
-
reject(error);
|
|
83
|
-
}
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Load language files
|
|
89
|
-
*/
|
|
90
|
-
loadLanguages() {
|
|
91
|
-
const languages = ['javascript', 'python', 'sql', 'bash', 'json'];
|
|
92
|
-
|
|
93
|
-
for (const lang of languages) {
|
|
94
|
-
const script = document.createElement('script');
|
|
95
|
-
script.src = `${this.config.cdnUrl}/components/prism-${lang}.js`;
|
|
96
|
-
script.async = true;
|
|
97
|
-
document.head.appendChild(script);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Highlight code
|
|
103
|
-
*/
|
|
104
|
-
async highlight(code, language = 'plaintext') {
|
|
105
|
-
if (!code) return '';
|
|
106
|
-
|
|
107
|
-
// Ensure Prism is loaded
|
|
108
|
-
if (this.config.lazyLoad) {
|
|
109
|
-
try {
|
|
110
|
-
await this.ensureLoaded();
|
|
111
|
-
} catch (error) {
|
|
112
|
-
console.warn('Prism loading failed, returning unformatted code');
|
|
113
|
-
return this.escapeHtml(code);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// Check cache
|
|
118
|
-
const cacheKey = `${language}:${code}`;
|
|
119
|
-
if (this.config.enableCache && this.highlightCache.has(cacheKey)) {
|
|
120
|
-
return this.highlightCache.get(cacheKey);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// Highlight code
|
|
124
|
-
let highlighted;
|
|
125
|
-
try {
|
|
126
|
-
if (typeof Prism !== 'undefined' && Prism.languages[language]) {
|
|
127
|
-
highlighted = Prism.highlight(code, Prism.languages[language], language);
|
|
128
|
-
} else {
|
|
129
|
-
// Fallback to escaped HTML if language not supported
|
|
130
|
-
highlighted = this.escapeHtml(code);
|
|
131
|
-
}
|
|
132
|
-
} catch (error) {
|
|
133
|
-
console.error('Highlight error:', error);
|
|
134
|
-
highlighted = this.escapeHtml(code);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// Cache result
|
|
138
|
-
if (this.config.enableCache) {
|
|
139
|
-
this.highlightCache.set(cacheKey, highlighted);
|
|
140
|
-
|
|
141
|
-
// Trim cache if too large
|
|
142
|
-
if (this.highlightCache.size > this.config.maxCacheSize) {
|
|
143
|
-
const firstKey = this.highlightCache.keys().next().value;
|
|
144
|
-
this.highlightCache.delete(firstKey);
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
return highlighted;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* Create highlighted code element
|
|
153
|
-
*/
|
|
154
|
-
async createHighlightedElement(code, language = 'plaintext') {
|
|
155
|
-
const pre = document.createElement('pre');
|
|
156
|
-
const code_el = document.createElement('code');
|
|
157
|
-
|
|
158
|
-
// Set language class
|
|
159
|
-
code_el.className = `language-${language}`;
|
|
160
|
-
|
|
161
|
-
if (this.config.lazyLoad) {
|
|
162
|
-
try {
|
|
163
|
-
await this.ensureLoaded();
|
|
164
|
-
const highlighted = await this.highlight(code, language);
|
|
165
|
-
code_el.innerHTML = highlighted;
|
|
166
|
-
} catch (error) {
|
|
167
|
-
code_el.textContent = code;
|
|
168
|
-
}
|
|
169
|
-
} else {
|
|
170
|
-
code_el.textContent = code;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
pre.appendChild(code_el);
|
|
174
|
-
return pre;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* Highlight DOM element
|
|
179
|
-
*/
|
|
180
|
-
async highlightElement(element) {
|
|
181
|
-
if (!element || !element.querySelector('code')) return;
|
|
182
|
-
|
|
183
|
-
if (this.config.lazyLoad) {
|
|
184
|
-
try {
|
|
185
|
-
await this.ensureLoaded();
|
|
186
|
-
} catch (error) {
|
|
187
|
-
console.warn('Prism loading failed, skipping highlighting');
|
|
188
|
-
return;
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
if (typeof Prism !== 'undefined') {
|
|
193
|
-
try {
|
|
194
|
-
Prism.highlightElement(element.querySelector('code'));
|
|
195
|
-
} catch (error) {
|
|
196
|
-
console.error('Element highlighting error:', error);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* Detect language from code content
|
|
203
|
-
*/
|
|
204
|
-
detectLanguage(code) {
|
|
205
|
-
if (!code) return 'plaintext';
|
|
206
|
-
|
|
207
|
-
// Shebang detection
|
|
208
|
-
if (code.startsWith('#!/')) {
|
|
209
|
-
if (code.includes('python')) return 'python';
|
|
210
|
-
if (code.includes('node') || code.includes('node.js')) return 'javascript';
|
|
211
|
-
if (code.includes('bash') || code.includes('sh')) return 'bash';
|
|
212
|
-
if (code.includes('ruby')) return 'ruby';
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
// Pattern detection
|
|
216
|
-
if (code.includes('def ') && code.includes(':')) return 'python';
|
|
217
|
-
if (code.includes('function') || code.includes('=>')) return 'javascript';
|
|
218
|
-
if (code.includes('fn ') && code.includes('->')) return 'rust';
|
|
219
|
-
if (code.includes('public static') || code.includes('class ')) return 'java';
|
|
220
|
-
if (code.includes('SELECT') || code.includes('INSERT')) return 'sql';
|
|
221
|
-
if (code.includes('<html') || code.includes('<div')) return 'html';
|
|
222
|
-
if (code.includes('::') && code.includes('use ')) return 'rust';
|
|
223
|
-
|
|
224
|
-
return 'plaintext';
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* Get supported languages
|
|
229
|
-
*/
|
|
230
|
-
getSupportedLanguages() {
|
|
231
|
-
return [...this.config.supportedLanguages];
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
/**
|
|
235
|
-
* Check if language is supported
|
|
236
|
-
*/
|
|
237
|
-
isSupportedLanguage(language) {
|
|
238
|
-
return this.config.supportedLanguages.includes(language);
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
/**
|
|
242
|
-
* Clear cache
|
|
243
|
-
*/
|
|
244
|
-
clearCache() {
|
|
245
|
-
this.highlightCache.clear();
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
/**
|
|
249
|
-
* Get cache stats
|
|
250
|
-
*/
|
|
251
|
-
getCacheStats() {
|
|
252
|
-
return {
|
|
253
|
-
size: this.highlightCache.size,
|
|
254
|
-
maxSize: this.config.maxCacheSize
|
|
255
|
-
};
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
/**
|
|
259
|
-
* HTML escape utility
|
|
260
|
-
*/
|
|
261
|
-
escapeHtml(text) {
|
|
262
|
-
return window._escHtml(text);
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
// Export for use in browser
|
|
267
|
-
if (typeof module !== 'undefined' && module.exports) {
|
|
268
|
-
module.exports = SyntaxHighlighter;
|
|
269
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Syntax Highlighter Integration
|
|
3
|
+
* Handles lazy-loading and caching of Prism.js for code highlighting
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
class SyntaxHighlighter {
|
|
7
|
+
constructor(config = {}) {
|
|
8
|
+
this.config = {
|
|
9
|
+
cdnUrl: config.cdnUrl || 'https://cdn.jsdelivr.net/npm/prismjs@1.29.0',
|
|
10
|
+
lazyLoad: config.lazyLoad !== false,
|
|
11
|
+
enableCache: config.enableCache !== false,
|
|
12
|
+
maxCacheSize: config.maxCacheSize || 500,
|
|
13
|
+
supportedLanguages: config.supportedLanguages || [
|
|
14
|
+
'javascript', 'typescript', 'python', 'java', 'cpp', 'c', 'csharp', 'go', 'rust',
|
|
15
|
+
'php', 'ruby', 'swift', 'kotlin', 'sql', 'html', 'css', 'scss', 'bash', 'shell',
|
|
16
|
+
'json', 'xml', 'yaml', 'markdown', 'plaintext'
|
|
17
|
+
],
|
|
18
|
+
...config
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
this.isLoaded = false;
|
|
22
|
+
this.isLoading = false;
|
|
23
|
+
this.highlightCache = new Map();
|
|
24
|
+
this.loadPromise = null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Ensure Prism is loaded
|
|
29
|
+
*/
|
|
30
|
+
async ensureLoaded() {
|
|
31
|
+
// Already loaded
|
|
32
|
+
if (typeof Prism !== 'undefined' && this.isLoaded) {
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Currently loading
|
|
37
|
+
if (this.isLoading && this.loadPromise) {
|
|
38
|
+
return this.loadPromise;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Start loading
|
|
42
|
+
this.isLoading = true;
|
|
43
|
+
this.loadPromise = this.loadPrism();
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
const result = await this.loadPromise;
|
|
47
|
+
this.isLoaded = true;
|
|
48
|
+
return result;
|
|
49
|
+
} catch (error) {
|
|
50
|
+
console.error('Failed to load Prism:', error);
|
|
51
|
+
this.isLoading = false;
|
|
52
|
+
throw error;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Load Prism library
|
|
58
|
+
*/
|
|
59
|
+
async loadPrism() {
|
|
60
|
+
return new Promise((resolve, reject) => {
|
|
61
|
+
try {
|
|
62
|
+
// Load main Prism JS
|
|
63
|
+
const script = document.createElement('script');
|
|
64
|
+
script.src = `${this.config.cdnUrl}/prism.js`;
|
|
65
|
+
script.async = true;
|
|
66
|
+
|
|
67
|
+
script.onload = () => {
|
|
68
|
+
// Load common language files
|
|
69
|
+
this.loadLanguages();
|
|
70
|
+
this.isLoading = false;
|
|
71
|
+
resolve(true);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
script.onerror = () => {
|
|
75
|
+
this.isLoading = false;
|
|
76
|
+
reject(new Error('Failed to load Prism.js'));
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
document.head.appendChild(script);
|
|
80
|
+
} catch (error) {
|
|
81
|
+
this.isLoading = false;
|
|
82
|
+
reject(error);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Load language files
|
|
89
|
+
*/
|
|
90
|
+
loadLanguages() {
|
|
91
|
+
const languages = ['javascript', 'python', 'sql', 'bash', 'json'];
|
|
92
|
+
|
|
93
|
+
for (const lang of languages) {
|
|
94
|
+
const script = document.createElement('script');
|
|
95
|
+
script.src = `${this.config.cdnUrl}/components/prism-${lang}.js`;
|
|
96
|
+
script.async = true;
|
|
97
|
+
document.head.appendChild(script);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Highlight code
|
|
103
|
+
*/
|
|
104
|
+
async highlight(code, language = 'plaintext') {
|
|
105
|
+
if (!code) return '';
|
|
106
|
+
|
|
107
|
+
// Ensure Prism is loaded
|
|
108
|
+
if (this.config.lazyLoad) {
|
|
109
|
+
try {
|
|
110
|
+
await this.ensureLoaded();
|
|
111
|
+
} catch (error) {
|
|
112
|
+
console.warn('Prism loading failed, returning unformatted code');
|
|
113
|
+
return this.escapeHtml(code);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Check cache
|
|
118
|
+
const cacheKey = `${language}:${code}`;
|
|
119
|
+
if (this.config.enableCache && this.highlightCache.has(cacheKey)) {
|
|
120
|
+
return this.highlightCache.get(cacheKey);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Highlight code
|
|
124
|
+
let highlighted;
|
|
125
|
+
try {
|
|
126
|
+
if (typeof Prism !== 'undefined' && Prism.languages[language]) {
|
|
127
|
+
highlighted = Prism.highlight(code, Prism.languages[language], language);
|
|
128
|
+
} else {
|
|
129
|
+
// Fallback to escaped HTML if language not supported
|
|
130
|
+
highlighted = this.escapeHtml(code);
|
|
131
|
+
}
|
|
132
|
+
} catch (error) {
|
|
133
|
+
console.error('Highlight error:', error);
|
|
134
|
+
highlighted = this.escapeHtml(code);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Cache result
|
|
138
|
+
if (this.config.enableCache) {
|
|
139
|
+
this.highlightCache.set(cacheKey, highlighted);
|
|
140
|
+
|
|
141
|
+
// Trim cache if too large
|
|
142
|
+
if (this.highlightCache.size > this.config.maxCacheSize) {
|
|
143
|
+
const firstKey = this.highlightCache.keys().next().value;
|
|
144
|
+
this.highlightCache.delete(firstKey);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return highlighted;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Create highlighted code element
|
|
153
|
+
*/
|
|
154
|
+
async createHighlightedElement(code, language = 'plaintext') {
|
|
155
|
+
const pre = document.createElement('pre');
|
|
156
|
+
const code_el = document.createElement('code');
|
|
157
|
+
|
|
158
|
+
// Set language class
|
|
159
|
+
code_el.className = `language-${language}`;
|
|
160
|
+
|
|
161
|
+
if (this.config.lazyLoad) {
|
|
162
|
+
try {
|
|
163
|
+
await this.ensureLoaded();
|
|
164
|
+
const highlighted = await this.highlight(code, language);
|
|
165
|
+
code_el.innerHTML = highlighted;
|
|
166
|
+
} catch (error) {
|
|
167
|
+
code_el.textContent = code;
|
|
168
|
+
}
|
|
169
|
+
} else {
|
|
170
|
+
code_el.textContent = code;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
pre.appendChild(code_el);
|
|
174
|
+
return pre;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Highlight DOM element
|
|
179
|
+
*/
|
|
180
|
+
async highlightElement(element) {
|
|
181
|
+
if (!element || !element.querySelector('code')) return;
|
|
182
|
+
|
|
183
|
+
if (this.config.lazyLoad) {
|
|
184
|
+
try {
|
|
185
|
+
await this.ensureLoaded();
|
|
186
|
+
} catch (error) {
|
|
187
|
+
console.warn('Prism loading failed, skipping highlighting');
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (typeof Prism !== 'undefined') {
|
|
193
|
+
try {
|
|
194
|
+
Prism.highlightElement(element.querySelector('code'));
|
|
195
|
+
} catch (error) {
|
|
196
|
+
console.error('Element highlighting error:', error);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Detect language from code content
|
|
203
|
+
*/
|
|
204
|
+
detectLanguage(code) {
|
|
205
|
+
if (!code) return 'plaintext';
|
|
206
|
+
|
|
207
|
+
// Shebang detection
|
|
208
|
+
if (code.startsWith('#!/')) {
|
|
209
|
+
if (code.includes('python')) return 'python';
|
|
210
|
+
if (code.includes('node') || code.includes('node.js')) return 'javascript';
|
|
211
|
+
if (code.includes('bash') || code.includes('sh')) return 'bash';
|
|
212
|
+
if (code.includes('ruby')) return 'ruby';
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Pattern detection
|
|
216
|
+
if (code.includes('def ') && code.includes(':')) return 'python';
|
|
217
|
+
if (code.includes('function') || code.includes('=>')) return 'javascript';
|
|
218
|
+
if (code.includes('fn ') && code.includes('->')) return 'rust';
|
|
219
|
+
if (code.includes('public static') || code.includes('class ')) return 'java';
|
|
220
|
+
if (code.includes('SELECT') || code.includes('INSERT')) return 'sql';
|
|
221
|
+
if (code.includes('<html') || code.includes('<div')) return 'html';
|
|
222
|
+
if (code.includes('::') && code.includes('use ')) return 'rust';
|
|
223
|
+
|
|
224
|
+
return 'plaintext';
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Get supported languages
|
|
229
|
+
*/
|
|
230
|
+
getSupportedLanguages() {
|
|
231
|
+
return [...this.config.supportedLanguages];
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Check if language is supported
|
|
236
|
+
*/
|
|
237
|
+
isSupportedLanguage(language) {
|
|
238
|
+
return this.config.supportedLanguages.includes(language);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Clear cache
|
|
243
|
+
*/
|
|
244
|
+
clearCache() {
|
|
245
|
+
this.highlightCache.clear();
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Get cache stats
|
|
250
|
+
*/
|
|
251
|
+
getCacheStats() {
|
|
252
|
+
return {
|
|
253
|
+
size: this.highlightCache.size,
|
|
254
|
+
maxSize: this.config.maxCacheSize
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* HTML escape utility
|
|
260
|
+
*/
|
|
261
|
+
escapeHtml(text) {
|
|
262
|
+
return window._escHtml(text);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// Export for use in browser
|
|
267
|
+
if (typeof module !== 'undefined' && module.exports) {
|
|
268
|
+
module.exports = SyntaxHighlighter;
|
|
269
|
+
}
|