@nicomatt69/streamtty 0.0.1
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/LICENSE +21 -0
- package/README.md +471 -0
- package/dist/ai-sdk-adapter.d.ts +113 -0
- package/dist/ai-sdk-adapter.d.ts.map +1 -0
- package/dist/ai-sdk-adapter.js +304 -0
- package/dist/ai-sdk-adapter.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +188 -0
- package/dist/cli.js.map +1 -0
- package/dist/errors.d.ts +131 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +346 -0
- package/dist/errors.js.map +1 -0
- package/dist/events.d.ts +185 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +350 -0
- package/dist/events.js.map +1 -0
- package/dist/index.d.ts +117 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +323 -0
- package/dist/index.js.map +1 -0
- package/dist/parser/streaming-parser.d.ts +81 -0
- package/dist/parser/streaming-parser.d.ts.map +1 -0
- package/dist/parser/streaming-parser.js +522 -0
- package/dist/parser/streaming-parser.js.map +1 -0
- package/dist/performance.d.ts +139 -0
- package/dist/performance.d.ts.map +1 -0
- package/dist/performance.js +401 -0
- package/dist/performance.js.map +1 -0
- package/dist/plugins/index.d.ts +6 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +22 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/plugins/plugin-system-inline.d.ts +116 -0
- package/dist/plugins/plugin-system-inline.d.ts.map +1 -0
- package/dist/plugins/plugin-system-inline.js +289 -0
- package/dist/plugins/plugin-system-inline.js.map +1 -0
- package/dist/plugins/plugin-system.d.ts +65 -0
- package/dist/plugins/plugin-system.d.ts.map +1 -0
- package/dist/plugins/plugin-system.js +202 -0
- package/dist/plugins/plugin-system.js.map +1 -0
- package/dist/plugins/rehype/harden.d.ts +15 -0
- package/dist/plugins/rehype/harden.d.ts.map +1 -0
- package/dist/plugins/rehype/harden.js +71 -0
- package/dist/plugins/rehype/harden.js.map +1 -0
- package/dist/plugins/rehype/index.d.ts +5 -0
- package/dist/plugins/rehype/index.d.ts.map +1 -0
- package/dist/plugins/rehype/index.js +21 -0
- package/dist/plugins/rehype/index.js.map +1 -0
- package/dist/plugins/remark/index.d.ts +6 -0
- package/dist/plugins/remark/index.d.ts.map +1 -0
- package/dist/plugins/remark/index.js +22 -0
- package/dist/plugins/remark/index.js.map +1 -0
- package/dist/plugins/remark/math.d.ts +7 -0
- package/dist/plugins/remark/math.d.ts.map +1 -0
- package/dist/plugins/remark/math.js +22 -0
- package/dist/plugins/remark/math.js.map +1 -0
- package/dist/plugins/remark/mermaid.d.ts +7 -0
- package/dist/plugins/remark/mermaid.d.ts.map +1 -0
- package/dist/plugins/remark/mermaid.js +19 -0
- package/dist/plugins/remark/mermaid.js.map +1 -0
- package/dist/plugins/types.d.ts +72 -0
- package/dist/plugins/types.d.ts.map +1 -0
- package/dist/plugins/types.js +3 -0
- package/dist/plugins/types.js.map +1 -0
- package/dist/renderer/blessed-renderer.d.ts +92 -0
- package/dist/renderer/blessed-renderer.d.ts.map +1 -0
- package/dist/renderer/blessed-renderer.js +610 -0
- package/dist/renderer/blessed-renderer.js.map +1 -0
- package/dist/renderers/index.d.ts +7 -0
- package/dist/renderers/index.d.ts.map +1 -0
- package/dist/renderers/index.js +21 -0
- package/dist/renderers/index.js.map +1 -0
- package/dist/renderers/math-renderer.d.ts +49 -0
- package/dist/renderers/math-renderer.d.ts.map +1 -0
- package/dist/renderers/math-renderer.js +193 -0
- package/dist/renderers/math-renderer.js.map +1 -0
- package/dist/renderers/mermaid-ascii.d.ts +14 -0
- package/dist/renderers/mermaid-ascii.d.ts.map +1 -0
- package/dist/renderers/mermaid-ascii.js +260 -0
- package/dist/renderers/mermaid-ascii.js.map +1 -0
- package/dist/renderers/mermaid-renderer.d.ts +79 -0
- package/dist/renderers/mermaid-renderer.d.ts.map +1 -0
- package/dist/renderers/mermaid-renderer.js +298 -0
- package/dist/renderers/mermaid-renderer.js.map +1 -0
- package/dist/renderers/shiki-ansi.d.ts +48 -0
- package/dist/renderers/shiki-ansi.d.ts.map +1 -0
- package/dist/renderers/shiki-ansi.js +206 -0
- package/dist/renderers/shiki-ansi.js.map +1 -0
- package/dist/renderers/table-ascii.d.ts +30 -0
- package/dist/renderers/table-ascii.d.ts.map +1 -0
- package/dist/renderers/table-ascii.js +243 -0
- package/dist/renderers/table-ascii.js.map +1 -0
- package/dist/renderers/table-renderer.d.ts +49 -0
- package/dist/renderers/table-renderer.d.ts.map +1 -0
- package/dist/renderers/table-renderer.js +224 -0
- package/dist/renderers/table-renderer.js.map +1 -0
- package/dist/renderers/unicode-math.d.ts +29 -0
- package/dist/renderers/unicode-math.d.ts.map +1 -0
- package/dist/renderers/unicode-math.js +181 -0
- package/dist/renderers/unicode-math.js.map +1 -0
- package/dist/security/ansi-sanitizer.d.ts +71 -0
- package/dist/security/ansi-sanitizer.d.ts.map +1 -0
- package/dist/security/ansi-sanitizer.js +275 -0
- package/dist/security/ansi-sanitizer.js.map +1 -0
- package/dist/security/chunk-processor.d.ts +81 -0
- package/dist/security/chunk-processor.d.ts.map +1 -0
- package/dist/security/chunk-processor.js +297 -0
- package/dist/security/chunk-processor.js.map +1 -0
- package/dist/security/index.d.ts +6 -0
- package/dist/security/index.d.ts.map +1 -0
- package/dist/security/index.js +22 -0
- package/dist/security/index.js.map +1 -0
- package/dist/security/input-validator.d.ts +55 -0
- package/dist/security/input-validator.d.ts.map +1 -0
- package/dist/security/input-validator.js +201 -0
- package/dist/security/input-validator.js.map +1 -0
- package/dist/stream-protocol.d.ts +61 -0
- package/dist/stream-protocol.d.ts.map +1 -0
- package/dist/stream-protocol.js +214 -0
- package/dist/stream-protocol.js.map +1 -0
- package/dist/streamdown-compat.d.ts +74 -0
- package/dist/streamdown-compat.d.ts.map +1 -0
- package/dist/streamdown-compat.js +241 -0
- package/dist/streamdown-compat.js.map +1 -0
- package/dist/streaming/stream-stats.d.ts +97 -0
- package/dist/streaming/stream-stats.d.ts.map +1 -0
- package/dist/streaming/stream-stats.js +217 -0
- package/dist/streaming/stream-stats.js.map +1 -0
- package/dist/streaming-integration.d.ts +71 -0
- package/dist/streaming-integration.d.ts.map +1 -0
- package/dist/streaming-integration.js +194 -0
- package/dist/streaming-integration.js.map +1 -0
- package/dist/themes/index.d.ts +59 -0
- package/dist/themes/index.d.ts.map +1 -0
- package/dist/themes/index.js +122 -0
- package/dist/themes/index.js.map +1 -0
- package/dist/types/index.d.ts +222 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/plugin-types.d.ts +5 -0
- package/dist/types/plugin-types.d.ts.map +1 -0
- package/dist/types/plugin-types.js +6 -0
- package/dist/types/plugin-types.js.map +1 -0
- package/dist/types/stream-events.d.ts +71 -0
- package/dist/types/stream-events.d.ts.map +1 -0
- package/dist/types/stream-events.js +10 -0
- package/dist/types/stream-events.js.map +1 -0
- package/dist/utils/blessed-syntax-highlighter.d.ts +124 -0
- package/dist/utils/blessed-syntax-highlighter.d.ts.map +1 -0
- package/dist/utils/blessed-syntax-highlighter.js +440 -0
- package/dist/utils/blessed-syntax-highlighter.js.map +1 -0
- package/dist/utils/enhanced-table-renderer.d.ts +77 -0
- package/dist/utils/enhanced-table-renderer.d.ts.map +1 -0
- package/dist/utils/enhanced-table-renderer.js +376 -0
- package/dist/utils/enhanced-table-renderer.js.map +1 -0
- package/dist/utils/formatting.d.ts +100 -0
- package/dist/utils/formatting.d.ts.map +1 -0
- package/dist/utils/formatting.js +220 -0
- package/dist/utils/formatting.js.map +1 -0
- package/dist/utils/index.d.ts +5 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +21 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/math-unicode-renderer.d.ts +38 -0
- package/dist/utils/math-unicode-renderer.d.ts.map +1 -0
- package/dist/utils/math-unicode-renderer.js +380 -0
- package/dist/utils/math-unicode-renderer.js.map +1 -0
- package/dist/utils/mermaid-ascii-renderer.d.ts +20 -0
- package/dist/utils/mermaid-ascii-renderer.d.ts.map +1 -0
- package/dist/utils/mermaid-ascii-renderer.js +325 -0
- package/dist/utils/mermaid-ascii-renderer.js.map +1 -0
- package/dist/utils/mermaid-ascii.d.ts +53 -0
- package/dist/utils/mermaid-ascii.d.ts.map +1 -0
- package/dist/utils/mermaid-ascii.js +181 -0
- package/dist/utils/mermaid-ascii.js.map +1 -0
- package/dist/utils/shiki-ansi-renderer.d.ts +29 -0
- package/dist/utils/shiki-ansi-renderer.d.ts.map +1 -0
- package/dist/utils/shiki-ansi-renderer.js +354 -0
- package/dist/utils/shiki-ansi-renderer.js.map +1 -0
- package/dist/utils/syntax-highlighter.d.ts +87 -0
- package/dist/utils/syntax-highlighter.d.ts.map +1 -0
- package/dist/utils/syntax-highlighter.js +265 -0
- package/dist/utils/syntax-highlighter.js.map +1 -0
- package/dist/utils/table-formatter-inline.d.ts +37 -0
- package/dist/utils/table-formatter-inline.d.ts.map +1 -0
- package/dist/utils/table-formatter-inline.js +337 -0
- package/dist/utils/table-formatter-inline.js.map +1 -0
- package/dist/utils/table.d.ts +35 -0
- package/dist/utils/table.d.ts.map +1 -0
- package/dist/utils/table.js +197 -0
- package/dist/utils/table.js.map +1 -0
- package/dist/widgets/stream-indicator.d.ts +130 -0
- package/dist/widgets/stream-indicator.d.ts.map +1 -0
- package/dist/widgets/stream-indicator.js +276 -0
- package/dist/widgets/stream-indicator.js.map +1 -0
- package/package.json +75 -0
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* KaTeX/LaTeX → Unicode inline rendering
|
|
4
|
+
* Semplice, niente HTML/blessed, output string puro
|
|
5
|
+
* Compatibile con streaming chunks
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.renderMathToUnicode = renderMathToUnicode;
|
|
9
|
+
exports.renderMathBlock = renderMathBlock;
|
|
10
|
+
exports.renderMathInline = renderMathInline;
|
|
11
|
+
exports.containsMath = containsMath;
|
|
12
|
+
exports.processMathInText = processMathInText;
|
|
13
|
+
// Symbol mapping: LaTeX → Unicode
|
|
14
|
+
const SYMBOL_MAP = {
|
|
15
|
+
// Greek letters
|
|
16
|
+
'alpha': 'α', 'beta': 'β', 'gamma': 'γ', 'delta': 'δ', 'epsilon': 'ε',
|
|
17
|
+
'zeta': 'ζ', 'eta': 'η', 'theta': 'θ', 'iota': 'ι', 'kappa': 'κ',
|
|
18
|
+
'lambda': 'λ', 'mu': 'μ', 'nu': 'ν', 'xi': 'ξ', 'omicron': 'ο',
|
|
19
|
+
'pi': 'π', 'rho': 'ρ', 'sigma': 'σ', 'tau': 'τ', 'upsilon': 'υ',
|
|
20
|
+
'phi': 'φ', 'chi': 'χ', 'psi': 'ψ', 'omega': 'ω',
|
|
21
|
+
// Math operators
|
|
22
|
+
'infty': '∞', 'inf': '∞',
|
|
23
|
+
'sum': '∑', 'prod': '∏', 'coprod': '∐',
|
|
24
|
+
'int': '∫', 'iint': '∬', 'iiint': '∭',
|
|
25
|
+
'sqrt': '√', 'cbrt': '∛',
|
|
26
|
+
'approx': '≈', 'neq': '≠', 'leq': '≤', 'geq': '≥',
|
|
27
|
+
'll': '≪', 'gg': '≫',
|
|
28
|
+
'pm': '±', 'mp': '∓',
|
|
29
|
+
'times': '×', 'div': '÷', 'cdot': '·',
|
|
30
|
+
'forall': '∀', 'exists': '∃', 'emptyset': '∅',
|
|
31
|
+
'in': '∈', 'ni': '∋', 'subset': '⊂', 'supset': '⊃',
|
|
32
|
+
'cap': '∩', 'cup': '∪',
|
|
33
|
+
'wedge': '∧', 'vee': '∨',
|
|
34
|
+
'neg': '¬', 'implies': '⇒', 'iff': '⇔',
|
|
35
|
+
'partial': '∂', 'nabla': '∇',
|
|
36
|
+
'dagger': '†', 'ddagger': '‡',
|
|
37
|
+
'star': '★', 'ast': '*',
|
|
38
|
+
'propto': '∝', 'angle': '∠',
|
|
39
|
+
'mid': '∣', 'parallel': '∥', 'perp': '⊥',
|
|
40
|
+
// Relations
|
|
41
|
+
'sim': '~', 'simeq': '≃', 'cong': '≅', 'equiv': '≡',
|
|
42
|
+
// Logical
|
|
43
|
+
'top': '⊤', 'bot': '⊥',
|
|
44
|
+
'oplus': '⊕', 'ominus': '⊖', 'otimes': '⊗', 'oslash': '⊘',
|
|
45
|
+
// Arrows
|
|
46
|
+
'to': '→', 'gets': '←', 'leftrightarrow': '↔',
|
|
47
|
+
'Rightarrow': '⇒', 'Leftarrow': '⇐', 'Leftrightarrow': '⇔',
|
|
48
|
+
'mapsto': '↦', 'longrightarrow': '→',
|
|
49
|
+
// Superscript digits
|
|
50
|
+
'0': '⁰', '1': '¹', '2': '²', '3': '³', '4': '⁴', '5': '⁵', '6': '⁶', '7': '⁷', '8': '⁸', '9': '⁹',
|
|
51
|
+
// Other
|
|
52
|
+
'degree': '°', 'prime': '′', 'dprime': '″',
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Render LaTeX/KaTeX to Unicode string
|
|
56
|
+
* @param latex LaTeX source string
|
|
57
|
+
* @param inline Whether it's inline (true) or display (false) mode
|
|
58
|
+
* @returns Rendered Unicode string
|
|
59
|
+
*/
|
|
60
|
+
function renderMathToUnicode(latex, inline = true) {
|
|
61
|
+
if (!latex || latex.trim().length === 0) {
|
|
62
|
+
return '';
|
|
63
|
+
}
|
|
64
|
+
let result = latex;
|
|
65
|
+
// 1. Replace \command{...} style symbols
|
|
66
|
+
result = result.replace(/\\([a-zA-Z]+)/g, (match, cmd) => {
|
|
67
|
+
const symbol = SYMBOL_MAP[cmd];
|
|
68
|
+
return symbol || match;
|
|
69
|
+
});
|
|
70
|
+
// 2. Handle superscript: x^2 → x²
|
|
71
|
+
result = result.replace(/\^(\{[^}]+\}|.)/g, (match, exp) => {
|
|
72
|
+
// Remove braces if present
|
|
73
|
+
const expContent = exp.replace(/[{}]/g, '');
|
|
74
|
+
// Convert each character
|
|
75
|
+
return expContent
|
|
76
|
+
.split('')
|
|
77
|
+
.map((char) => {
|
|
78
|
+
const superscripts = {
|
|
79
|
+
'0': '⁰', '1': '¹', '2': '²', '3': '³', '4': '⁴',
|
|
80
|
+
'5': '⁵', '6': '⁶', '7': '⁷', '8': '⁸', '9': '⁹',
|
|
81
|
+
'+': '⁺', '-': '⁻', '=': '⁼', '(': '⁽', ')': '⁾',
|
|
82
|
+
'n': 'ⁿ', 'i': 'ⁱ', 'a': 'ᵃ', 'x': 'ˣ',
|
|
83
|
+
};
|
|
84
|
+
return superscripts[char] || char;
|
|
85
|
+
})
|
|
86
|
+
.join('');
|
|
87
|
+
});
|
|
88
|
+
// 3. Handle subscript: x_i → xᵢ (fallback: x[i])
|
|
89
|
+
result = result.replace(/_(\{[^}]+\}|.)/g, (match, sub) => {
|
|
90
|
+
const subContent = sub.replace(/[{}]/g, '');
|
|
91
|
+
// Limited subscript support
|
|
92
|
+
const subscripts = {
|
|
93
|
+
'0': '₀', '1': '₁', '2': '₂', '3': '₃', '4': '₄',
|
|
94
|
+
'5': '₅', '6': '₆', '7': '₇', '8': '₈', '9': '₉',
|
|
95
|
+
'+': '₊', '-': '₋', '=': '₌', '(': '₍', ')': '₎',
|
|
96
|
+
'i': 'ᵢ', 'n': 'ₙ', 'x': 'ₓ',
|
|
97
|
+
};
|
|
98
|
+
const converted = subContent
|
|
99
|
+
.split('')
|
|
100
|
+
.map((char) => subscripts[char] || char)
|
|
101
|
+
.join('');
|
|
102
|
+
// Fallback: if no subscript support, use [i] notation
|
|
103
|
+
return converted === subContent ? `[${subContent}]` : converted;
|
|
104
|
+
});
|
|
105
|
+
// 4. Fractions: \frac{a}{b} → (a)/(b) or a/b
|
|
106
|
+
result = result.replace(/\\frac\{([^}]+)\}\{([^}]+)\}/g, (match, num, denom) => {
|
|
107
|
+
// For inline, use compact form
|
|
108
|
+
if (inline) {
|
|
109
|
+
return `${num}/${denom}`;
|
|
110
|
+
}
|
|
111
|
+
// For display, could format as multi-line but we keep it simple
|
|
112
|
+
return `\n(${num})\n─────\n(${denom})\n`;
|
|
113
|
+
});
|
|
114
|
+
// 5. Radicals: \sqrt{x} → √(x), \sqrt[3]{x} → ∛(x)
|
|
115
|
+
result = result.replace(/\\sqrt(?:\[(\d)\])?\{([^}]+)\}/g, (match, root, radicand) => {
|
|
116
|
+
const rootNum = root || '2';
|
|
117
|
+
const radical = rootNum === '2' ? '√' : rootNum === '3' ? '∛' : `√[${rootNum}]`;
|
|
118
|
+
return `${radical}(${radicand})`;
|
|
119
|
+
});
|
|
120
|
+
// 6. Limits: \sum_{i=1}^{n} → ∑(i=1 to n)
|
|
121
|
+
result = result.replace(/([∑∏∫])_\{([^}]+)\}\^\{([^}]+)\}/g, '$1($2→$3)');
|
|
122
|
+
// 7. Clean up remaining braces
|
|
123
|
+
result = result.replace(/[{}]/g, '');
|
|
124
|
+
// 8. Handle common LaTeX sequences
|
|
125
|
+
result = result
|
|
126
|
+
.replace(/\\\\/g, '\n') // Line breaks
|
|
127
|
+
.replace(/\\left/g, '')
|
|
128
|
+
.replace(/\\right/g, '')
|
|
129
|
+
.replace(/\\middle/g, '')
|
|
130
|
+
.replace(/\\limits/g, '');
|
|
131
|
+
// 9. Remove empty braces
|
|
132
|
+
result = result.replace(/\(\)/g, '');
|
|
133
|
+
return result.trim();
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Render display mode math (block, possibly multi-line)
|
|
137
|
+
*/
|
|
138
|
+
function renderMathBlock(latex) {
|
|
139
|
+
const content = renderMathToUnicode(latex, false);
|
|
140
|
+
// Box the content for visual separation
|
|
141
|
+
const lines = content.split('\n').map(l => l.trim()).filter(Boolean);
|
|
142
|
+
if (lines.length === 0)
|
|
143
|
+
return '';
|
|
144
|
+
const maxLen = Math.max(...lines.map(l => l.length));
|
|
145
|
+
const padding = 2;
|
|
146
|
+
const width = maxLen + padding * 2;
|
|
147
|
+
let boxed = '\n┌' + '─'.repeat(width) + '┐\n';
|
|
148
|
+
for (const line of lines) {
|
|
149
|
+
const spaces = ' '.repeat(padding + (width - padding * 2 - line.length) / 2);
|
|
150
|
+
boxed += `│${spaces}${line}${spaces}│\n`;
|
|
151
|
+
}
|
|
152
|
+
boxed += '└' + '─'.repeat(width) + '┘\n';
|
|
153
|
+
return boxed;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Render inline math (no newlines)
|
|
157
|
+
*/
|
|
158
|
+
function renderMathInline(latex) {
|
|
159
|
+
return renderMathToUnicode(latex, true);
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Detect if text contains math expressions
|
|
163
|
+
*/
|
|
164
|
+
function containsMath(text) {
|
|
165
|
+
return /(\$\$[^\$]+\$\$|\$[^\$]+\$|\\(.+?)(?=\s|$))/g.test(text);
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Extract and process all math expressions in text
|
|
169
|
+
*/
|
|
170
|
+
function processMathInText(text) {
|
|
171
|
+
return text
|
|
172
|
+
// Display math: $$ ... $$
|
|
173
|
+
.replace(/\$\$([^\$]+)\$\$/g, (match, latex) => {
|
|
174
|
+
return renderMathBlock(latex);
|
|
175
|
+
})
|
|
176
|
+
// Inline math: $ ... $
|
|
177
|
+
.replace(/\$([^\$]+)\$/g, (match, latex) => {
|
|
178
|
+
return renderMathInline(latex);
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=unicode-math.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unicode-math.js","sourceRoot":"","sources":["../../src/renderers/unicode-math.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ANSI Code Sanitizer
|
|
3
|
+
* Prevents ANSI injection attacks while preserving safe color codes
|
|
4
|
+
*/
|
|
5
|
+
export interface SanitizationOptions {
|
|
6
|
+
stripAnsi?: boolean;
|
|
7
|
+
maxLength?: number;
|
|
8
|
+
allowUnicode?: boolean;
|
|
9
|
+
stripControlChars?: boolean;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Sanitize input for terminal output
|
|
13
|
+
* Removes dangerous sequences while preserving safe ANSI color codes
|
|
14
|
+
*/
|
|
15
|
+
export declare function sanitizeForTerminal(input: string, options?: SanitizationOptions): string;
|
|
16
|
+
/**
|
|
17
|
+
* Validate input for safety
|
|
18
|
+
*/
|
|
19
|
+
export interface ValidationResult {
|
|
20
|
+
valid: boolean;
|
|
21
|
+
errors: string[];
|
|
22
|
+
warnings: string[];
|
|
23
|
+
sanitized: string;
|
|
24
|
+
}
|
|
25
|
+
export declare function validateInput(input: string, maxLength?: number): ValidationResult;
|
|
26
|
+
/**
|
|
27
|
+
* Strip all ANSI codes (for logging, etc.)
|
|
28
|
+
*/
|
|
29
|
+
export declare function stripAnsiCodes(text: string): string;
|
|
30
|
+
/**
|
|
31
|
+
* Check if text contains ANSI codes
|
|
32
|
+
*/
|
|
33
|
+
export declare function hasAnsiCodes(text: string): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Count visible characters (excluding ANSI codes)
|
|
36
|
+
*/
|
|
37
|
+
export declare function getVisibleLength(text: string): number;
|
|
38
|
+
/**
|
|
39
|
+
* Truncate text to visible length, preserving ANSI codes
|
|
40
|
+
*/
|
|
41
|
+
export declare function truncatePreservingAnsi(text: string, maxVisible: number): string;
|
|
42
|
+
/**
|
|
43
|
+
* Create a content security policy validator
|
|
44
|
+
*/
|
|
45
|
+
export declare class ContentValidator {
|
|
46
|
+
private maxLength;
|
|
47
|
+
private maxLines;
|
|
48
|
+
private allowedPatterns;
|
|
49
|
+
private blockedPatterns;
|
|
50
|
+
constructor(config?: {
|
|
51
|
+
maxLength?: number;
|
|
52
|
+
maxLines?: number;
|
|
53
|
+
});
|
|
54
|
+
/**
|
|
55
|
+
* Add allowed pattern
|
|
56
|
+
*/
|
|
57
|
+
allowPattern(pattern: RegExp): void;
|
|
58
|
+
/**
|
|
59
|
+
* Add blocked pattern
|
|
60
|
+
*/
|
|
61
|
+
blockPattern(pattern: RegExp): void;
|
|
62
|
+
/**
|
|
63
|
+
* Validate content
|
|
64
|
+
*/
|
|
65
|
+
validate(content: string): ValidationResult;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Export validator instance
|
|
69
|
+
*/
|
|
70
|
+
export declare const defaultValidator: ContentValidator;
|
|
71
|
+
//# sourceMappingURL=ansi-sanitizer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ansi-sanitizer.d.ts","sourceRoot":"","sources":["../../src/security/ansi-sanitizer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,mBAAmB;IAClC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AA0DD;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,mBAAmB,GAC5B,MAAM,CA4ER;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,GAAE,MAAgB,GAAG,gBAAgB,CAyC1F;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAElD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAErD;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAuB/E;AAED;;GAEG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,eAAe,CAAgB;IACvC,OAAO,CAAC,eAAe,CAAgB;gBAE3B,MAAM,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE;IAK9D;;OAEG;IACH,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAInC;;OAEG;IACH,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAInC;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB;CAsC5C;AAED;;GAEG;AACH,eAAO,MAAM,gBAAgB,kBAAyB,CAAC"}
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ANSI Code Sanitizer
|
|
4
|
+
* Prevents ANSI injection attacks while preserving safe color codes
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.defaultValidator = exports.ContentValidator = void 0;
|
|
8
|
+
exports.sanitizeForTerminal = sanitizeForTerminal;
|
|
9
|
+
exports.validateInput = validateInput;
|
|
10
|
+
exports.stripAnsiCodes = stripAnsiCodes;
|
|
11
|
+
exports.hasAnsiCodes = hasAnsiCodes;
|
|
12
|
+
exports.getVisibleLength = getVisibleLength;
|
|
13
|
+
exports.truncatePreservingAnsi = truncatePreservingAnsi;
|
|
14
|
+
/**
|
|
15
|
+
* Safe ANSI escape codes that are allowed
|
|
16
|
+
*/
|
|
17
|
+
const SAFE_ANSI_PATTERNS = [
|
|
18
|
+
/\x1b\[\d{1,3}(?:;\d{1,3})*m/g, // Colors (SGR - Select Graphic Rendition)
|
|
19
|
+
/\x1b\[2K/g, // Erase entire line
|
|
20
|
+
/\x1b\[0J/g, // Erase from cursor to end of display
|
|
21
|
+
];
|
|
22
|
+
/**
|
|
23
|
+
* Dangerous ANSI patterns that should be stripped
|
|
24
|
+
*/
|
|
25
|
+
const DANGEROUS_ANSI_PATTERNS = [
|
|
26
|
+
/\x1b\]\d*;[^\x07]*\x07/g, // OSC (Operating System Command)
|
|
27
|
+
/\x1b\]\d*;[^\x1b]*(?:\x1b\\|\x1b\])/g, // OSC alternative
|
|
28
|
+
/\x1b\[[?0-9;]*[sS]/g, // Save/restore cursor
|
|
29
|
+
/\x1b\[[?0-9;]*[AB]/g, // Cursor movement
|
|
30
|
+
/\x1b\[s/g, // Save cursor
|
|
31
|
+
/\x1b\[u/g, // Restore cursor
|
|
32
|
+
/\x1b\[H/g, // Cursor home
|
|
33
|
+
/\x1b\[J/g, // Erase display
|
|
34
|
+
/\x00/g, // Null bytes (DoS)
|
|
35
|
+
/\x1b\[[?0-9;]*h/g, // Set mode
|
|
36
|
+
/\x1b\[[?0-9;]*l/g, // Reset mode
|
|
37
|
+
];
|
|
38
|
+
/**
|
|
39
|
+
* Control characters to filter
|
|
40
|
+
*/
|
|
41
|
+
const DANGEROUS_CONTROL_CHARS = [
|
|
42
|
+
'\x00', // Null
|
|
43
|
+
'\x01', // SOH (Start of Heading)
|
|
44
|
+
'\x02', // STX (Start of Text)
|
|
45
|
+
'\x03', // ETX (End of Text)
|
|
46
|
+
'\x04', // EOT (End of Transmission)
|
|
47
|
+
'\x05', // ENQ (Enquiry)
|
|
48
|
+
'\x06', // ACK (Acknowledge)
|
|
49
|
+
'\x07', // BEL (Bell)
|
|
50
|
+
'\x08', // BS (Backspace)
|
|
51
|
+
'\x0E', // SO (Shift Out)
|
|
52
|
+
'\x0F', // SI (Shift In)
|
|
53
|
+
'\x10', // DLE (Data Link Escape)
|
|
54
|
+
'\x11', // DC1 (Device Control 1)
|
|
55
|
+
'\x12', // DC2 (Device Control 2)
|
|
56
|
+
'\x13', // DC3 (Device Control 3)
|
|
57
|
+
'\x14', // DC4 (Device Control 4)
|
|
58
|
+
'\x15', // NAK (Negative Acknowledge)
|
|
59
|
+
'\x16', // SYN (Synchronous Idle)
|
|
60
|
+
'\x17', // ETB (End of Transmission Block)
|
|
61
|
+
'\x18', // CAN (Cancel)
|
|
62
|
+
'\x19', // EM (End of Medium)
|
|
63
|
+
'\x1A', // SUB (Substitute)
|
|
64
|
+
'\x1B', // ESC is allowed (it's part of ANSI codes)
|
|
65
|
+
'\x7F', // DEL (Delete)
|
|
66
|
+
];
|
|
67
|
+
/**
|
|
68
|
+
* Sanitize input for terminal output
|
|
69
|
+
* Removes dangerous sequences while preserving safe ANSI color codes
|
|
70
|
+
*/
|
|
71
|
+
function sanitizeForTerminal(input, options) {
|
|
72
|
+
if (!input)
|
|
73
|
+
return input;
|
|
74
|
+
const { stripAnsi = false, maxLength = 1000000, allowUnicode = true, stripControlChars = true, } = options || {};
|
|
75
|
+
let result = input;
|
|
76
|
+
// Check length
|
|
77
|
+
if (result.length > maxLength) {
|
|
78
|
+
console.warn(`Input exceeds max length (${maxLength}), truncating`);
|
|
79
|
+
result = result.substring(0, maxLength);
|
|
80
|
+
}
|
|
81
|
+
// Strip dangerous ANSI sequences first
|
|
82
|
+
for (const pattern of DANGEROUS_ANSI_PATTERNS) {
|
|
83
|
+
result = result.replace(pattern, '');
|
|
84
|
+
}
|
|
85
|
+
// Handle safe ANSI codes
|
|
86
|
+
if (stripAnsi) {
|
|
87
|
+
// Remove all ANSI codes
|
|
88
|
+
result = result.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, '');
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
// Keep safe codes only - validate they match safe patterns
|
|
92
|
+
const unsafeAnsiCodes = [];
|
|
93
|
+
// Extract all ANSI-like sequences
|
|
94
|
+
const allAnsiRegex = /\x1b\[[0-9;]*[a-zA-Z]/g;
|
|
95
|
+
let match;
|
|
96
|
+
while ((match = allAnsiRegex.exec(result)) !== null) {
|
|
97
|
+
let isSafe = false;
|
|
98
|
+
// Check against safe patterns
|
|
99
|
+
for (const pattern of SAFE_ANSI_PATTERNS) {
|
|
100
|
+
const testRegex = new RegExp(`^${pattern.source}$`);
|
|
101
|
+
if (testRegex.test(match[0])) {
|
|
102
|
+
isSafe = true;
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
if (!isSafe) {
|
|
107
|
+
// Mark for removal
|
|
108
|
+
unsafeAnsiCodes.push({ code: match[0], index: match.index });
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// Remove unsafe codes (reverse iteration to preserve indices)
|
|
112
|
+
for (let i = unsafeAnsiCodes.length - 1; i >= 0; i--) {
|
|
113
|
+
const item = unsafeAnsiCodes[i];
|
|
114
|
+
result = result.substring(0, item.index) + result.substring(item.index + item.code.length);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
// Strip control characters if requested
|
|
118
|
+
if (stripControlChars) {
|
|
119
|
+
for (const char of DANGEROUS_CONTROL_CHARS) {
|
|
120
|
+
result = result.split(char).join('');
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// Unicode validation if needed
|
|
124
|
+
if (!allowUnicode) {
|
|
125
|
+
result = result.replace(/[^\x00-\x7F]/g, '?');
|
|
126
|
+
}
|
|
127
|
+
// Remove consecutive null bytes (DoS attempt)
|
|
128
|
+
result = result.replace(/\x00+/g, '');
|
|
129
|
+
return result;
|
|
130
|
+
}
|
|
131
|
+
function validateInput(input, maxLength = 1000000) {
|
|
132
|
+
const errors = [];
|
|
133
|
+
const warnings = [];
|
|
134
|
+
let sanitized = input;
|
|
135
|
+
// Check length
|
|
136
|
+
if (input.length > maxLength) {
|
|
137
|
+
errors.push(`Input exceeds maximum length of ${maxLength}`);
|
|
138
|
+
sanitized = sanitized.substring(0, maxLength);
|
|
139
|
+
}
|
|
140
|
+
// Check for dangerous patterns
|
|
141
|
+
if (/\x1b\].*?\x07/.test(input)) {
|
|
142
|
+
warnings.push('OSC sequences detected (stripped)');
|
|
143
|
+
}
|
|
144
|
+
if (/\x00/.test(input)) {
|
|
145
|
+
errors.push('Null bytes detected');
|
|
146
|
+
sanitized = sanitized.replace(/\x00/g, '');
|
|
147
|
+
}
|
|
148
|
+
// Check for excessive ANSI codes (possible DoS)
|
|
149
|
+
const ansiCount = (input.match(/\x1b\[/g) || []).length;
|
|
150
|
+
if (ansiCount > 1000) {
|
|
151
|
+
warnings.push(`Excessive ANSI codes detected (${ansiCount})`);
|
|
152
|
+
}
|
|
153
|
+
// Sanitize
|
|
154
|
+
sanitized = sanitizeForTerminal(sanitized, {
|
|
155
|
+
stripAnsi: false,
|
|
156
|
+
maxLength,
|
|
157
|
+
allowUnicode: true,
|
|
158
|
+
stripControlChars: true,
|
|
159
|
+
});
|
|
160
|
+
return {
|
|
161
|
+
valid: errors.length === 0,
|
|
162
|
+
errors,
|
|
163
|
+
warnings,
|
|
164
|
+
sanitized,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Strip all ANSI codes (for logging, etc.)
|
|
169
|
+
*/
|
|
170
|
+
function stripAnsiCodes(text) {
|
|
171
|
+
return text.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, '');
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Check if text contains ANSI codes
|
|
175
|
+
*/
|
|
176
|
+
function hasAnsiCodes(text) {
|
|
177
|
+
return /\x1b\[[0-9;]*[a-zA-Z]/.test(text);
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Count visible characters (excluding ANSI codes)
|
|
181
|
+
*/
|
|
182
|
+
function getVisibleLength(text) {
|
|
183
|
+
return stripAnsiCodes(text).length;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Truncate text to visible length, preserving ANSI codes
|
|
187
|
+
*/
|
|
188
|
+
function truncatePreservingAnsi(text, maxVisible) {
|
|
189
|
+
let visibleCount = 0;
|
|
190
|
+
let result = '';
|
|
191
|
+
let i = 0;
|
|
192
|
+
while (i < text.length && visibleCount < maxVisible) {
|
|
193
|
+
if (text[i] === '\x1b') {
|
|
194
|
+
// Found ANSI code start
|
|
195
|
+
const endIdx = text.indexOf('m', i);
|
|
196
|
+
if (endIdx !== -1) {
|
|
197
|
+
// Include entire ANSI code
|
|
198
|
+
result += text.substring(i, endIdx + 1);
|
|
199
|
+
i = endIdx + 1;
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
result += text[i];
|
|
204
|
+
visibleCount++;
|
|
205
|
+
i++;
|
|
206
|
+
}
|
|
207
|
+
return result;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Create a content security policy validator
|
|
211
|
+
*/
|
|
212
|
+
class ContentValidator {
|
|
213
|
+
maxLength;
|
|
214
|
+
maxLines;
|
|
215
|
+
allowedPatterns = [];
|
|
216
|
+
blockedPatterns = [];
|
|
217
|
+
constructor(config) {
|
|
218
|
+
this.maxLength = config?.maxLength ?? 1000000;
|
|
219
|
+
this.maxLines = config?.maxLines ?? 10000;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Add allowed pattern
|
|
223
|
+
*/
|
|
224
|
+
allowPattern(pattern) {
|
|
225
|
+
this.allowedPatterns.push(pattern);
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Add blocked pattern
|
|
229
|
+
*/
|
|
230
|
+
blockPattern(pattern) {
|
|
231
|
+
this.blockedPatterns.push(pattern);
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Validate content
|
|
235
|
+
*/
|
|
236
|
+
validate(content) {
|
|
237
|
+
const result = {
|
|
238
|
+
valid: true,
|
|
239
|
+
errors: [],
|
|
240
|
+
warnings: [],
|
|
241
|
+
sanitized: content,
|
|
242
|
+
};
|
|
243
|
+
// Length check
|
|
244
|
+
if (content.length > this.maxLength) {
|
|
245
|
+
result.errors.push(`Content exceeds maximum length (${this.maxLength})`);
|
|
246
|
+
result.valid = false;
|
|
247
|
+
}
|
|
248
|
+
// Line count check
|
|
249
|
+
const lineCount = content.split('\n').length;
|
|
250
|
+
if (lineCount > this.maxLines) {
|
|
251
|
+
result.errors.push(`Content exceeds maximum lines (${this.maxLines})`);
|
|
252
|
+
result.valid = false;
|
|
253
|
+
}
|
|
254
|
+
// Check blocked patterns
|
|
255
|
+
for (const pattern of this.blockedPatterns) {
|
|
256
|
+
if (pattern.test(content)) {
|
|
257
|
+
result.warnings.push(`Blocked pattern detected: ${pattern.source}`);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
// Sanitize
|
|
261
|
+
result.sanitized = sanitizeForTerminal(content, {
|
|
262
|
+
stripAnsi: false,
|
|
263
|
+
maxLength: this.maxLength,
|
|
264
|
+
allowUnicode: true,
|
|
265
|
+
stripControlChars: true,
|
|
266
|
+
});
|
|
267
|
+
return result;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
exports.ContentValidator = ContentValidator;
|
|
271
|
+
/**
|
|
272
|
+
* Export validator instance
|
|
273
|
+
*/
|
|
274
|
+
exports.defaultValidator = new ContentValidator();
|
|
275
|
+
//# sourceMappingURL=ansi-sanitizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ansi-sanitizer.js","sourceRoot":"","sources":["../../src/security/ansi-sanitizer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inline security validation and sanitization for streaming chunks
|
|
3
|
+
* Handles all 10 edge cases for robust streaming
|
|
4
|
+
*/
|
|
5
|
+
export interface ValidationResult {
|
|
6
|
+
valid: boolean;
|
|
7
|
+
error?: string;
|
|
8
|
+
sanitized?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface SanitizationOptions {
|
|
11
|
+
mode?: 'strict' | 'balanced' | 'permissive';
|
|
12
|
+
maxBufferSize?: number;
|
|
13
|
+
stripControlChars?: boolean;
|
|
14
|
+
stripDangerousAnsi?: boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Edge Case 1: Validate empty chunks
|
|
18
|
+
*/
|
|
19
|
+
export declare function isEmptyChunk(chunk: string): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Edge Case 2: Handle very large chunks (> 50KB)
|
|
22
|
+
*/
|
|
23
|
+
export declare function handleLargeChunk(chunk: string, maxSize?: number): string;
|
|
24
|
+
/**
|
|
25
|
+
* Edge Case 3: Normalize mixed line endings
|
|
26
|
+
* Handles \r\n, \r, and \n
|
|
27
|
+
*/
|
|
28
|
+
export declare function normalizeLineEndings(chunk: string): string;
|
|
29
|
+
/**
|
|
30
|
+
* Edge Case 4: Decode HTML entities comprehensively
|
|
31
|
+
*/
|
|
32
|
+
export declare function decodeHtmlEntities(chunk: string): string;
|
|
33
|
+
/**
|
|
34
|
+
* Edge Case 5: Unicode normalization NFC
|
|
35
|
+
*/
|
|
36
|
+
export declare function normalizeUnicode(chunk: string): string;
|
|
37
|
+
/**
|
|
38
|
+
* Edge Case 6: Validate UTF-8 encoding
|
|
39
|
+
*/
|
|
40
|
+
export declare function validateUTF8(chunk: string): {
|
|
41
|
+
valid: boolean;
|
|
42
|
+
error?: string;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Edge Case 7: Strip dangerous ANSI escape sequences
|
|
46
|
+
* Keep safe ones for terminal colors
|
|
47
|
+
*/
|
|
48
|
+
export declare function stripDangerousAnsiCodes(chunk: string): string;
|
|
49
|
+
/**
|
|
50
|
+
* Edge Case 8: Remove control characters (but keep safe ones)
|
|
51
|
+
*/
|
|
52
|
+
export declare function stripControlChars(chunk: string): string;
|
|
53
|
+
/**
|
|
54
|
+
* Edge Case 9: Remove null bytes
|
|
55
|
+
*/
|
|
56
|
+
export declare function stripNullBytes(chunk: string): string;
|
|
57
|
+
/**
|
|
58
|
+
* Edge Case 10: Validate bracket/brace nesting depth
|
|
59
|
+
* Prevents stack overflow attacks
|
|
60
|
+
*/
|
|
61
|
+
export declare function validateNestingDepth(chunk: string, maxDepth?: number): {
|
|
62
|
+
valid: boolean;
|
|
63
|
+
depth: number;
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Comprehensive chunk validation
|
|
67
|
+
*/
|
|
68
|
+
export declare function validateChunk(chunk: string): ValidationResult;
|
|
69
|
+
/**
|
|
70
|
+
* Comprehensive chunk sanitization (handles all edge cases)
|
|
71
|
+
*/
|
|
72
|
+
export declare function sanitizeChunk(chunk: string, options?: SanitizationOptions): string;
|
|
73
|
+
/**
|
|
74
|
+
* Full validation + sanitization pipeline
|
|
75
|
+
*/
|
|
76
|
+
export declare function processChunk(chunk: string, options?: SanitizationOptions): ValidationResult;
|
|
77
|
+
/**
|
|
78
|
+
* Detect suspicious patterns
|
|
79
|
+
*/
|
|
80
|
+
export declare function detectSuspiciousPatterns(chunk: string): string[];
|
|
81
|
+
//# sourceMappingURL=chunk-processor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunk-processor.d.ts","sourceRoot":"","sources":["../../src/security/chunk-processor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,QAAQ,GAAG,UAAU,GAAG,YAAY,CAAA;IAC3C,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAC7B;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,MAAkB,GAAG,MAAM,CAsBnF;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAI1D;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAwCxD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOtD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAkB9E;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAiB7D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAgBvD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAY,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAiB7G;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,gBAAgB,CAmB7D;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,mBAAwB,GAChC,MAAM,CA2CR;AAED;;GAEG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,mBAAwB,GAChC,gBAAgB,CAclB;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAyBhE"}
|