agentgui 1.0.127 → 1.0.128
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/package.json +1 -1
- package/static/js/streaming-renderer.js +50 -67
package/package.json
CHANGED
|
@@ -991,81 +991,64 @@ class StreamingRenderer {
|
|
|
991
991
|
* Render code with basic syntax highlighting
|
|
992
992
|
*/
|
|
993
993
|
static renderCodeWithHighlight(code, esc) {
|
|
994
|
-
//
|
|
995
|
-
|
|
994
|
+
// Tokenize-then-replace approach: collect spans as tokens so regexes
|
|
995
|
+
// never see previously-injected HTML, preventing cascading corruption.
|
|
996
|
+
const tokens = [];
|
|
997
|
+
const mkToken = (cls, text) => {
|
|
998
|
+
const id = `\x00T${tokens.length}\x00`;
|
|
999
|
+
tokens.push({ id, cls, text });
|
|
1000
|
+
return id;
|
|
1001
|
+
};
|
|
1002
|
+
|
|
1003
|
+
let src = code;
|
|
996
1004
|
|
|
997
|
-
// Detect
|
|
1005
|
+
// Detect JSON
|
|
998
1006
|
const isJSON = (code.trim().startsWith('{') || code.trim().startsWith('[')) &&
|
|
999
1007
|
code.includes('"') && (code.includes(':') || code.includes(','));
|
|
1000
1008
|
|
|
1001
1009
|
if (isJSON) {
|
|
1002
|
-
// JSON
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
// Booleans and null
|
|
1011
|
-
{ pattern: /:\s*(true|false|null)/g, replacement: ': <span style="color:#ef4444">$1</span>' },
|
|
1012
|
-
// Array/object brackets
|
|
1013
|
-
{ pattern: /([\[\]{}])/g, replacement: '<span style="color:#6b7280;font-weight:600">$1</span>' },
|
|
1014
|
-
];
|
|
1015
|
-
|
|
1016
|
-
jsonHighlights.forEach(({ pattern, replacement }) => {
|
|
1017
|
-
highlighted = highlighted.replace(pattern, replacement);
|
|
1018
|
-
});
|
|
1010
|
+
// JSON keys
|
|
1011
|
+
src = src.replace(/"([^"]+)"\s*:/g, (m, k) => `"${mkToken('jk', k)}":`);
|
|
1012
|
+
// JSON string values
|
|
1013
|
+
src = src.replace(/:\s*"([^"]*)"/g, (m, v) => `: "${mkToken('js', v)}"`);
|
|
1014
|
+
// JSON numbers
|
|
1015
|
+
src = src.replace(/:\s*(\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)/g, (m, n) => `: ${mkToken('jn', n)}`);
|
|
1016
|
+
// JSON booleans/null
|
|
1017
|
+
src = src.replace(/:\s*(true|false|null)/g, (m, b) => `: ${mkToken('jb', b)}`);
|
|
1019
1018
|
} else {
|
|
1020
|
-
//
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
// Function/method names (improved)
|
|
1051
|
-
{ pattern: /\b([a-zA-Z_][a-zA-Z0-9_]*)(?=\s*\()/g, replacement: '<span style="color:#3b82f6">$1</span>' },
|
|
1052
|
-
|
|
1053
|
-
// Operators
|
|
1054
|
-
{ pattern: /(===|!==|==|!=|<=|>=|&&|\|\||\+=|-=|\*=|\/=|%=|=>|->)/g, replacement: '<span style="color:#a855f7">$1</span>' },
|
|
1055
|
-
];
|
|
1056
|
-
|
|
1057
|
-
// Apply highlights
|
|
1058
|
-
highlights.forEach(({ pattern, replacement }) => {
|
|
1059
|
-
if (typeof replacement === 'function') {
|
|
1060
|
-
highlighted = highlighted.replace(pattern, replacement);
|
|
1061
|
-
} else {
|
|
1062
|
-
highlighted = highlighted.replace(pattern, replacement);
|
|
1063
|
-
}
|
|
1064
|
-
});
|
|
1019
|
+
// Comments
|
|
1020
|
+
src = src.replace(/(\/\/[^\n]*)/g, (m) => mkToken('cm', m));
|
|
1021
|
+
src = src.replace(/(\/\*[\s\S]*?\*\/)/g, (m) => mkToken('cm', m));
|
|
1022
|
+
src = src.replace(/(#[^\n]*)/g, (m) => mkToken('cm', m));
|
|
1023
|
+
// Strings
|
|
1024
|
+
src = src.replace(/(["'])(?:[^\\]|\\.)*?\1/g, (m) => mkToken('st', m));
|
|
1025
|
+
src = src.replace(/`([^`]*)`/g, (m) => mkToken('st', m));
|
|
1026
|
+
// Keywords
|
|
1027
|
+
src = src.replace(/\b(function|const|let|var|class|import|export|async|await|return|if|else|for|while|try|catch|throw|new|typeof|instanceof|this|super|switch|case|default|break|continue|do|def|from|elif|except|raise|with|as|lambda|pass|yield|global|nonlocal|public|private|protected|static|final|abstract|interface|extends|implements|package|void)\b/g, (m) => mkToken('kw', m));
|
|
1028
|
+
// Booleans/null
|
|
1029
|
+
src = src.replace(/\b(true|false|null|undefined|None|True|False|nil)\b/g, (m) => mkToken('bl', m));
|
|
1030
|
+
// Numbers
|
|
1031
|
+
src = src.replace(/\b(\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)\b/g, (m) => mkToken('nu', m));
|
|
1032
|
+
// Functions
|
|
1033
|
+
src = src.replace(/\b([a-zA-Z_][a-zA-Z0-9_]*)(?=\s*\()/g, (m) => mkToken('fn', m));
|
|
1034
|
+
// Operators
|
|
1035
|
+
src = src.replace(/(===|!==|==|!=|<=|>=|&&|\|\||\+=|-=|\*=|\/=|%=|=>|->)/g, (m) => mkToken('op', m));
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
// Now escape HTML on the tokenized source (tokens are safe null-byte markers)
|
|
1039
|
+
let highlighted = esc(src);
|
|
1040
|
+
|
|
1041
|
+
// Replace tokens with actual styled spans
|
|
1042
|
+
const styles = {
|
|
1043
|
+
jk: 'color:#3b82f6;font-weight:600', js: 'color:#10b981', jn: 'color:#f59e0b', jb: 'color:#ef4444',
|
|
1044
|
+
cm: 'color:#6b7280;font-style:italic', st: 'color:#10b981', kw: 'color:#8b5cf6;font-weight:600',
|
|
1045
|
+
bl: 'color:#ef4444', nu: 'color:#f59e0b', fn: 'color:#3b82f6', op: 'color:#a855f7'
|
|
1046
|
+
};
|
|
1047
|
+
for (const { id, cls, text } of tokens) {
|
|
1048
|
+
highlighted = highlighted.replace(id, `<span style="${styles[cls]}">${esc(text)}</span>`);
|
|
1065
1049
|
}
|
|
1066
1050
|
|
|
1067
|
-
|
|
1068
|
-
return `<pre style="background:#1e293b;padding:1rem;border-radius:0.375rem;overflow-x:auto;font-family:'Monaco','Menlo','Ubuntu Mono',monospace;font-size:0.875rem;line-height:1.6;color:#e2e8f0;border:1px solid #334155;box-shadow:0 2px 4px rgba(0,0,0,0.1)">${highlighted}</pre>`;
|
|
1051
|
+
return `<pre style="background:#1e293b;padding:1rem;border-radius:0.375rem;overflow-x:auto;font-family:'Monaco','Menlo','Ubuntu Mono',monospace;font-size:0.875rem;line-height:1.6;color:#e2e8f0;border:1px solid #334155">${highlighted}</pre>`;
|
|
1069
1052
|
}
|
|
1070
1053
|
|
|
1071
1054
|
/**
|