@cendor/squeeze 0.2.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.
- package/LICENSE +201 -0
- package/README.md +47 -0
- package/dist/.tsbuildinfo +1 -0
- package/dist/index.d.ts +65 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +550 -0
- package/dist/index.js.map +1 -0
- package/dist/json.d.ts +28 -0
- package/dist/json.d.ts.map +1 -0
- package/dist/json.js +250 -0
- package/dist/json.js.map +1 -0
- package/dist/store.d.ts +44 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +104 -0
- package/dist/store.js.map +1 -0
- package/dist/text.d.ts +26 -0
- package/dist/text.d.ts.map +1 -0
- package/dist/text.js +109 -0
- package/dist/text.js.map +1 -0
- package/package.json +51 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,550 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@cendor/squeeze` — content-aware, reversible context compression. The TS port of
|
|
3
|
+
* `cendor.squeeze`.
|
|
4
|
+
*
|
|
5
|
+
* Shrink verbose context without throwing anything away: {@link compress} returns `[small, handle]`
|
|
6
|
+
* and `handle.expand()` restores the original on demand. Content is routed by type — JSON, logs,
|
|
7
|
+
* code, and prose each get a purpose-built, deterministic compressor (no LLM). Reversibility is
|
|
8
|
+
* guaranteed by a content-addressed store (CCR): every original is kept keyed by its hash, deduped
|
|
9
|
+
* across calls, so `expand()` is always exact no matter how hard we squeeze.
|
|
10
|
+
*
|
|
11
|
+
* Satisfies `@cendor/core`'s `Compressor` protocol by shape (see {@link SqueezeCompressor}).
|
|
12
|
+
*/
|
|
13
|
+
import { createHash } from 'node:crypto';
|
|
14
|
+
import { tokens } from '@cendor/core';
|
|
15
|
+
import { dumps, parseJson } from './json.js';
|
|
16
|
+
import { MemoryStore } from './store.js';
|
|
17
|
+
import { isAsciiDigit, isPySpace, pyLStrip, pyRStrip, pyStrip, rstripChars, splitlines, } from './text.js';
|
|
18
|
+
export { KeyError, MemoryStore, SQLiteStore } from './store.js';
|
|
19
|
+
const FIDELITY = ['lossless', 'balanced', 'aggressive'];
|
|
20
|
+
const TIMES = String.fromCharCode(0xd7); // U+00D7 MULTIPLICATION SIGN (not ASCII 'x')
|
|
21
|
+
/** Raised on invalid `fidelity` (mirrors Python's `ValueError`). */
|
|
22
|
+
class ValueError extends Error {
|
|
23
|
+
constructor(message) {
|
|
24
|
+
super(message);
|
|
25
|
+
this.name = 'ValueError';
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function pyRepr(s) {
|
|
29
|
+
return `'${s.replace(/\\/g, '\\\\').replace(/'/g, "\\'")}'`;
|
|
30
|
+
}
|
|
31
|
+
// --------------------------------------------------------------------------- CCR backend
|
|
32
|
+
// Active content-addressed store: sha256(original) -> original. Deduped; the basis of reversibility.
|
|
33
|
+
// Default in-process; swap via useStore() for a persistent backend.
|
|
34
|
+
let backend = new MemoryStore();
|
|
35
|
+
/**
|
|
36
|
+
* Swap the CCR backend (e.g. `SQLiteStore`); returns the previous one. A backend is any object with
|
|
37
|
+
* `get(key) -> string` and `put(key, value) -> void`. Handles expand against whichever backend is
|
|
38
|
+
* active at expand time.
|
|
39
|
+
*/
|
|
40
|
+
export function useStore(store) {
|
|
41
|
+
const previous = backend;
|
|
42
|
+
backend = store;
|
|
43
|
+
return previous;
|
|
44
|
+
}
|
|
45
|
+
/** The active backend (test/inspection accessor; not part of the stable public surface). */
|
|
46
|
+
export function _backend() {
|
|
47
|
+
return backend;
|
|
48
|
+
}
|
|
49
|
+
function sha256Hex(s) {
|
|
50
|
+
return createHash('sha256').update(s, 'utf8').digest('hex');
|
|
51
|
+
}
|
|
52
|
+
function store(original) {
|
|
53
|
+
const key = sha256Hex(original);
|
|
54
|
+
backend.put(key, original);
|
|
55
|
+
return key;
|
|
56
|
+
}
|
|
57
|
+
// --------------------------------------------------------------------------- Handle
|
|
58
|
+
/** Restore handle for a compression. `expand()` returns the exact original. */
|
|
59
|
+
export class Handle {
|
|
60
|
+
id;
|
|
61
|
+
kind;
|
|
62
|
+
originalRef;
|
|
63
|
+
restoreMap;
|
|
64
|
+
constructor(id, kind, originalRef, restoreMap = {}) {
|
|
65
|
+
this.id = id;
|
|
66
|
+
this.kind = kind;
|
|
67
|
+
this.originalRef = originalRef;
|
|
68
|
+
this.restoreMap = restoreMap;
|
|
69
|
+
}
|
|
70
|
+
/** Return the original content, byte-for-byte (from the active CCR backend). */
|
|
71
|
+
expand() {
|
|
72
|
+
return backend.get(this.originalRef);
|
|
73
|
+
}
|
|
74
|
+
/** The compression technique recorded for this handle (e.g. `"minify+dropnulls"`). */
|
|
75
|
+
get technique() {
|
|
76
|
+
const t = this.restoreMap.technique;
|
|
77
|
+
return t === undefined || t === null ? '' : String(t);
|
|
78
|
+
}
|
|
79
|
+
/** Serialize the handle (not the original). Persist it alongside a durable store. */
|
|
80
|
+
toDict() {
|
|
81
|
+
return {
|
|
82
|
+
id: this.id,
|
|
83
|
+
kind: this.kind,
|
|
84
|
+
original_ref: this.originalRef,
|
|
85
|
+
restore_map: { ...this.restoreMap },
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
/** Rebuild a handle from {@link toDict}; `expand()` resolves via the active store. */
|
|
89
|
+
static fromDict(data) {
|
|
90
|
+
return new Handle(String(data.id), String(data.kind), String(data.original_ref), {
|
|
91
|
+
...(data.restore_map ?? {}),
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// --------------------------------------------------------------------------- detection
|
|
96
|
+
const TS_SRC = '\\b\\d{4}-\\d{2}-\\d{2}[T ]\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+-]\\d{2}:?\\d{2})?\\b';
|
|
97
|
+
const UUID_SRC = '\\b[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}\\b';
|
|
98
|
+
const IP_SRC = '\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b';
|
|
99
|
+
const HEX_SRC = '\\b0x[0-9a-fA-F]+\\b|\\b[0-9a-fA-F]{8,}\\b';
|
|
100
|
+
const INT_SRC = '\\b\\d+\\b';
|
|
101
|
+
// Global variants for `.replace` (all occurrences); non-global for `.test` (stateless).
|
|
102
|
+
const TS_RE = new RegExp(TS_SRC, 'g');
|
|
103
|
+
const UUID_RE = new RegExp(UUID_SRC, 'g');
|
|
104
|
+
const IP_RE = new RegExp(IP_SRC, 'g');
|
|
105
|
+
const HEX_RE = new RegExp(HEX_SRC, 'g');
|
|
106
|
+
const INT_RE = new RegExp(INT_SRC, 'g');
|
|
107
|
+
const TS_SEARCH = new RegExp(TS_SRC);
|
|
108
|
+
const LEVEL_RE = /\b(?:DEBUG|INFO|WARN|WARNING|ERROR|CRITICAL|TRACE|FATAL)\b/;
|
|
109
|
+
const CODE_MARKERS = [
|
|
110
|
+
'def ',
|
|
111
|
+
'class ',
|
|
112
|
+
'function ',
|
|
113
|
+
'func ',
|
|
114
|
+
'import ',
|
|
115
|
+
'from ',
|
|
116
|
+
'return ',
|
|
117
|
+
'const ',
|
|
118
|
+
'let ',
|
|
119
|
+
'var ',
|
|
120
|
+
'public ',
|
|
121
|
+
'private ',
|
|
122
|
+
'#include',
|
|
123
|
+
'=>',
|
|
124
|
+
'</',
|
|
125
|
+
];
|
|
126
|
+
// Preprocessor/import directives that begin with `#` but must NOT be stripped as comments.
|
|
127
|
+
const PREPROC_STICKY = /#\s*(?:include|define|undef|ifdef|ifndef|endif|else|elif|if|pragma|error|line|import)\b/y;
|
|
128
|
+
/** Detect the content kind: `"json"` | `"logs"` | `"code"` | `"prose"`. */
|
|
129
|
+
export function detect(content) {
|
|
130
|
+
const s = pyStrip(content);
|
|
131
|
+
if (s === '')
|
|
132
|
+
return 'prose';
|
|
133
|
+
const c0 = s[0];
|
|
134
|
+
if (c0 === '{' || c0 === '[') {
|
|
135
|
+
try {
|
|
136
|
+
parseJson(s);
|
|
137
|
+
return 'json';
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
// not JSON — fall through
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
if (looksLikeLogs(s))
|
|
144
|
+
return 'logs';
|
|
145
|
+
if (looksLikeCode(s))
|
|
146
|
+
return 'code';
|
|
147
|
+
return 'prose';
|
|
148
|
+
}
|
|
149
|
+
function nonBlankLines(s) {
|
|
150
|
+
return splitlines(s).filter((ln) => pyStrip(ln) !== '');
|
|
151
|
+
}
|
|
152
|
+
function looksLikeLogs(s) {
|
|
153
|
+
const lines = nonBlankLines(s);
|
|
154
|
+
if (lines.length < 3)
|
|
155
|
+
return false;
|
|
156
|
+
let hits = 0;
|
|
157
|
+
for (const ln of lines)
|
|
158
|
+
if (TS_SEARCH.test(ln) || LEVEL_RE.test(ln))
|
|
159
|
+
hits++;
|
|
160
|
+
return hits >= lines.length * 0.5;
|
|
161
|
+
}
|
|
162
|
+
function looksLikeCode(s) {
|
|
163
|
+
const lines = nonBlankLines(s);
|
|
164
|
+
if (lines.length === 0)
|
|
165
|
+
return false;
|
|
166
|
+
let hits = 0;
|
|
167
|
+
for (const ln of lines) {
|
|
168
|
+
const st = pyStrip(ln);
|
|
169
|
+
const endsSpecial = st.endsWith('{') || st.endsWith('}') || st.endsWith(';') || st.endsWith(':');
|
|
170
|
+
if (CODE_MARKERS.some((m) => ln.includes(m)) || endsSpecial)
|
|
171
|
+
hits++;
|
|
172
|
+
}
|
|
173
|
+
return hits >= Math.max(1, lines.length * 0.3);
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Compress `content` and return `[small, handle]`. `handle.expand()` restores it byte-for-byte.
|
|
177
|
+
*
|
|
178
|
+
* @param content A string, or a JSON-serializable object/array.
|
|
179
|
+
* @param opts `kind` (`"auto"` detects), `targetTokens` (best-effort budget, never exceeded),
|
|
180
|
+
* `model` (for token counting, default `"gpt-4o"`), `fidelity` (`"lossless" | "balanced" |
|
|
181
|
+
* "aggressive"`, default `"balanced"`).
|
|
182
|
+
*/
|
|
183
|
+
export function compress(content, opts = {}) {
|
|
184
|
+
const fidelity = opts.fidelity ?? 'balanced';
|
|
185
|
+
const targetTokens = opts.targetTokens ?? null;
|
|
186
|
+
const model = opts.model ?? 'gpt-4o';
|
|
187
|
+
let kind = opts.kind ?? 'auto';
|
|
188
|
+
if (!FIDELITY.includes(fidelity)) {
|
|
189
|
+
throw new ValueError(`fidelity must be one of ('lossless', 'balanced', 'aggressive'), got ${pyRepr(String(fidelity))}`);
|
|
190
|
+
}
|
|
191
|
+
let original;
|
|
192
|
+
if (typeof content === 'string') {
|
|
193
|
+
original = content;
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
original = dumps(content);
|
|
197
|
+
if (kind === 'auto')
|
|
198
|
+
kind = 'json';
|
|
199
|
+
}
|
|
200
|
+
if (kind === 'auto')
|
|
201
|
+
kind = detect(original);
|
|
202
|
+
let small;
|
|
203
|
+
let restoreMap;
|
|
204
|
+
if (kind === 'json') {
|
|
205
|
+
[small, restoreMap] = compressJson(original, targetTokens, model, fidelity);
|
|
206
|
+
}
|
|
207
|
+
else if (kind === 'logs') {
|
|
208
|
+
[small, restoreMap] = compressLogs(original, targetTokens, model);
|
|
209
|
+
}
|
|
210
|
+
else if (kind === 'code') {
|
|
211
|
+
[small, restoreMap] = compressCode(original, targetTokens, model, fidelity);
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
[small, restoreMap] = compressProse(original, targetTokens, model, fidelity);
|
|
215
|
+
}
|
|
216
|
+
const ref = store(original);
|
|
217
|
+
// Deterministic id (squeeze is deterministic): derived from the content-addressed ref + technique,
|
|
218
|
+
// so identical (content, technique) yields the same id. First 32 hex chars of sha256(`ref:tech`).
|
|
219
|
+
const technique = restoreMap.technique === undefined ? '' : String(restoreMap.technique);
|
|
220
|
+
const id = sha256Hex(`${ref}:${technique}`).slice(0, 32);
|
|
221
|
+
const handle = new Handle(id, kind, ref, restoreMap);
|
|
222
|
+
return [small, handle];
|
|
223
|
+
}
|
|
224
|
+
/** Restore the original content for a handle (same as `handle.expand()`). */
|
|
225
|
+
export function decompress(handle) {
|
|
226
|
+
return handle.expand();
|
|
227
|
+
}
|
|
228
|
+
/** Object form satisfying `@cendor/core`'s `Compressor` protocol (delegates to {@link compress}). */
|
|
229
|
+
export class SqueezeCompressor {
|
|
230
|
+
compress(content, opts = {}) {
|
|
231
|
+
return compress(content, {
|
|
232
|
+
kind: opts.kind ?? 'auto',
|
|
233
|
+
targetTokens: opts.targetTokens ?? null,
|
|
234
|
+
model: opts.model ?? 'gpt-4o',
|
|
235
|
+
fidelity: opts.fidelity ?? 'balanced',
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
// --------------------------------------------------------------------------- compressors
|
|
240
|
+
function stripNulls(obj) {
|
|
241
|
+
if (obj instanceof Map) {
|
|
242
|
+
const out = new Map();
|
|
243
|
+
for (const [k, v] of obj)
|
|
244
|
+
if (v !== null)
|
|
245
|
+
out.set(k, stripNulls(v));
|
|
246
|
+
return out;
|
|
247
|
+
}
|
|
248
|
+
if (Array.isArray(obj))
|
|
249
|
+
return obj.map(stripNulls);
|
|
250
|
+
return obj;
|
|
251
|
+
}
|
|
252
|
+
// Code-point length, matching Python `len()` (used only for stable drop-ordering).
|
|
253
|
+
function cpLen(s) {
|
|
254
|
+
let n = 0;
|
|
255
|
+
for (const _ of s)
|
|
256
|
+
n++;
|
|
257
|
+
return n;
|
|
258
|
+
}
|
|
259
|
+
function fitJson(obj, target, model) {
|
|
260
|
+
let small = dumps(obj);
|
|
261
|
+
if (tokens.count(small, model) <= target)
|
|
262
|
+
return [small, false];
|
|
263
|
+
if (obj instanceof Map) {
|
|
264
|
+
const kept = new Map(obj);
|
|
265
|
+
// sort keys by minified-value length, largest first; stable (ties keep insertion order).
|
|
266
|
+
const decorated = [...obj.keys()].map((k, idx) => ({
|
|
267
|
+
k,
|
|
268
|
+
idx,
|
|
269
|
+
len: cpLen(dumps(obj.get(k))),
|
|
270
|
+
}));
|
|
271
|
+
decorated.sort((a, b) => b.len - a.len || a.idx - b.idx);
|
|
272
|
+
for (const { k } of decorated) {
|
|
273
|
+
if (tokens.count(dumps(kept), model) <= target)
|
|
274
|
+
break;
|
|
275
|
+
kept.delete(k);
|
|
276
|
+
}
|
|
277
|
+
small = dumps(kept);
|
|
278
|
+
if (tokens.count(small, model) <= target)
|
|
279
|
+
return [small, true];
|
|
280
|
+
}
|
|
281
|
+
else if (Array.isArray(obj)) {
|
|
282
|
+
const keptList = [...obj];
|
|
283
|
+
while (keptList.length > 0 && tokens.count(dumps(keptList), model) > target)
|
|
284
|
+
keptList.pop();
|
|
285
|
+
small = dumps(keptList);
|
|
286
|
+
if (tokens.count(small, model) <= target)
|
|
287
|
+
return [small, true];
|
|
288
|
+
}
|
|
289
|
+
// last resort: a single giant scalar/leaf — prefix-cut (may not parse; documented).
|
|
290
|
+
return [truncateToTokens(small, target, model), true];
|
|
291
|
+
}
|
|
292
|
+
function compressJson(text, targetTokens, model, fidelity) {
|
|
293
|
+
let obj;
|
|
294
|
+
try {
|
|
295
|
+
obj = parseJson(text);
|
|
296
|
+
}
|
|
297
|
+
catch {
|
|
298
|
+
return compressProse(text, targetTokens, model, 'balanced');
|
|
299
|
+
}
|
|
300
|
+
const shaped = fidelity === 'lossless' ? obj : stripNulls(obj);
|
|
301
|
+
let technique = fidelity === 'lossless' ? 'minify' : 'minify+dropnulls';
|
|
302
|
+
if (targetTokens === null)
|
|
303
|
+
return [dumps(shaped), { technique }];
|
|
304
|
+
const [small, dropped] = fitJson(shaped, targetTokens, model);
|
|
305
|
+
if (dropped)
|
|
306
|
+
technique += '+drop';
|
|
307
|
+
return [small, { technique }];
|
|
308
|
+
}
|
|
309
|
+
function compressCode(text, targetTokens, model, fidelity) {
|
|
310
|
+
let code = text;
|
|
311
|
+
if (fidelity !== 'lossless')
|
|
312
|
+
code = stripComments(code);
|
|
313
|
+
const out = [];
|
|
314
|
+
for (const raw of splitlines(code)) {
|
|
315
|
+
let line = pyRStrip(raw);
|
|
316
|
+
if (pyStrip(line) === '')
|
|
317
|
+
continue;
|
|
318
|
+
if (fidelity === 'aggressive') {
|
|
319
|
+
const stripped = pyLStrip(line);
|
|
320
|
+
const indent = line.slice(0, line.length - stripped.length);
|
|
321
|
+
line = indent + stripped.replace(/[ \t]{2,}/g, ' ');
|
|
322
|
+
}
|
|
323
|
+
out.push(line);
|
|
324
|
+
}
|
|
325
|
+
let small = out.join('\n');
|
|
326
|
+
if (targetTokens !== null && tokens.count(small, model) > targetTokens) {
|
|
327
|
+
small = truncateToTokens(small, targetTokens, model);
|
|
328
|
+
}
|
|
329
|
+
return [small, { technique: `code:${fidelity}` }];
|
|
330
|
+
}
|
|
331
|
+
function normalizeLogLine(line) {
|
|
332
|
+
let out = line.replace(TS_RE, '<ts>');
|
|
333
|
+
out = out.replace(UUID_RE, '<uuid>');
|
|
334
|
+
out = out.replace(IP_RE, '<ip>');
|
|
335
|
+
out = out.replace(HEX_RE, '<hex>');
|
|
336
|
+
return out.replace(INT_RE, '<n>');
|
|
337
|
+
}
|
|
338
|
+
function compressLogs(text, targetTokens, model) {
|
|
339
|
+
const counts = new Map();
|
|
340
|
+
const order = [];
|
|
341
|
+
for (const line of splitlines(text)) {
|
|
342
|
+
const norm = normalizeLogLine(line);
|
|
343
|
+
if (!counts.has(norm))
|
|
344
|
+
order.push(norm);
|
|
345
|
+
counts.set(norm, (counts.get(norm) ?? 0) + 1);
|
|
346
|
+
}
|
|
347
|
+
const rendered = new Map();
|
|
348
|
+
for (const norm of order) {
|
|
349
|
+
const c = counts.get(norm);
|
|
350
|
+
rendered.set(norm, c > 1 ? `${norm} (${TIMES}${c})` : norm);
|
|
351
|
+
}
|
|
352
|
+
let kept;
|
|
353
|
+
if (targetTokens === null) {
|
|
354
|
+
kept = order;
|
|
355
|
+
}
|
|
356
|
+
else {
|
|
357
|
+
const chosen = new Set();
|
|
358
|
+
let running = 0;
|
|
359
|
+
// most-frequent first, stable (ties keep chronological order).
|
|
360
|
+
const decorated = order.map((norm, idx) => ({ norm, idx, c: counts.get(norm) }));
|
|
361
|
+
decorated.sort((a, b) => b.c - a.c || a.idx - b.idx);
|
|
362
|
+
for (const { norm } of decorated) {
|
|
363
|
+
const cost = tokens.count(rendered.get(norm), model) + 1; // +1 for the separator
|
|
364
|
+
if (running + cost > targetTokens && chosen.size > 0)
|
|
365
|
+
break; // first pattern always kept
|
|
366
|
+
chosen.add(norm);
|
|
367
|
+
running += cost;
|
|
368
|
+
}
|
|
369
|
+
kept = order.filter((norm) => chosen.has(norm)); // back to chronological order
|
|
370
|
+
}
|
|
371
|
+
let small = kept.map((norm) => rendered.get(norm)).join('\n');
|
|
372
|
+
if (targetTokens !== null && tokens.count(small, model) > targetTokens) {
|
|
373
|
+
small = truncateToTokens(small, targetTokens, model);
|
|
374
|
+
}
|
|
375
|
+
return [small, { technique: 'normalize+dedup', patterns: order.length }];
|
|
376
|
+
}
|
|
377
|
+
function stripComments(code) {
|
|
378
|
+
const out = [];
|
|
379
|
+
let i = 0;
|
|
380
|
+
const n = code.length;
|
|
381
|
+
let quote = null;
|
|
382
|
+
let inBlock = false;
|
|
383
|
+
let atLineStart = true; // no non-space char seen yet on the current line
|
|
384
|
+
while (i < n) {
|
|
385
|
+
const ch = code[i];
|
|
386
|
+
const nxt = i + 1 < n ? code[i + 1] : '';
|
|
387
|
+
if (inBlock) {
|
|
388
|
+
if (ch === '*' && nxt === '/') {
|
|
389
|
+
inBlock = false;
|
|
390
|
+
i += 2;
|
|
391
|
+
}
|
|
392
|
+
else {
|
|
393
|
+
if (ch === '\n')
|
|
394
|
+
out.push('\n'); // preserve newlines inside block comments
|
|
395
|
+
i += 1;
|
|
396
|
+
}
|
|
397
|
+
continue;
|
|
398
|
+
}
|
|
399
|
+
if (quote !== null) {
|
|
400
|
+
out.push(ch);
|
|
401
|
+
if (ch === '\\' && i + 1 < n) {
|
|
402
|
+
out.push(nxt); // escape — copy the escaped char verbatim
|
|
403
|
+
i += 2;
|
|
404
|
+
continue;
|
|
405
|
+
}
|
|
406
|
+
if (ch === quote)
|
|
407
|
+
quote = null;
|
|
408
|
+
i += 1;
|
|
409
|
+
continue;
|
|
410
|
+
}
|
|
411
|
+
if (ch === '"' || ch === "'" || ch === '`') {
|
|
412
|
+
quote = ch;
|
|
413
|
+
out.push(ch);
|
|
414
|
+
atLineStart = false;
|
|
415
|
+
i += 1;
|
|
416
|
+
continue;
|
|
417
|
+
}
|
|
418
|
+
if (ch === '/' && nxt === '/') {
|
|
419
|
+
while (i < n && code[i] !== '\n')
|
|
420
|
+
i += 1;
|
|
421
|
+
continue;
|
|
422
|
+
}
|
|
423
|
+
if (ch === '/' && nxt === '*') {
|
|
424
|
+
inBlock = true;
|
|
425
|
+
i += 2;
|
|
426
|
+
continue;
|
|
427
|
+
}
|
|
428
|
+
if (ch === '#' && !((atLineStart && nxt === '!') || preprocMatch(code, i))) {
|
|
429
|
+
while (i < n && code[i] !== '\n')
|
|
430
|
+
i += 1;
|
|
431
|
+
continue;
|
|
432
|
+
}
|
|
433
|
+
if (ch === '\n')
|
|
434
|
+
atLineStart = true;
|
|
435
|
+
else if (!isPySpace(ch))
|
|
436
|
+
atLineStart = false;
|
|
437
|
+
out.push(ch);
|
|
438
|
+
i += 1;
|
|
439
|
+
}
|
|
440
|
+
return out.join('');
|
|
441
|
+
}
|
|
442
|
+
function preprocMatch(code, i) {
|
|
443
|
+
PREPROC_STICKY.lastIndex = i;
|
|
444
|
+
return PREPROC_STICKY.test(code);
|
|
445
|
+
}
|
|
446
|
+
const SENT_RE = /(?<=[.!?])\s+/;
|
|
447
|
+
const LAST_WORD_RE = /([A-Za-z][A-Za-z.]*)\.?\s*$/;
|
|
448
|
+
const WORD_RE = /[a-zA-Z']+/g;
|
|
449
|
+
const STOP = new Set('the a an and or but of to in on for with is are was were be been it this that as at by'.split(' '));
|
|
450
|
+
// Abbreviations that end in a period but don't end a sentence. Compared lowercase, trailing dots
|
|
451
|
+
// stripped; note "e.g" / "i.e" keep their internal dot.
|
|
452
|
+
const ABBREV = new Set('dr mr mrs ms prof sr jr st vs etc no fig eq al inc ltd co e.g i.e cf approx dept vol pp'.split(' '));
|
|
453
|
+
/** Split prose into sentences, but don't break after a common abbreviation or a decimal. */
|
|
454
|
+
export function _splitSentences(text) {
|
|
455
|
+
const out = [];
|
|
456
|
+
for (const part of pyStrip(text).split(SENT_RE)) {
|
|
457
|
+
if (part === '')
|
|
458
|
+
continue;
|
|
459
|
+
if (out.length > 0) {
|
|
460
|
+
const prev = out[out.length - 1];
|
|
461
|
+
const m = prev.match(LAST_WORD_RE);
|
|
462
|
+
const tail = m ? rstripChars(m[1], '.').toLowerCase() : '';
|
|
463
|
+
const trimmed = rstripChars(pyRStrip(prev), '.');
|
|
464
|
+
const lastChar = trimmed.slice(-1);
|
|
465
|
+
const endsNumber = lastChar !== '' && isAsciiDigit(lastChar);
|
|
466
|
+
if (ABBREV.has(tail) || endsNumber) {
|
|
467
|
+
out[out.length - 1] = `${prev} ${part}`;
|
|
468
|
+
continue;
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
out.push(part);
|
|
472
|
+
}
|
|
473
|
+
return out.filter((s) => pyStrip(s) !== '');
|
|
474
|
+
}
|
|
475
|
+
function compressProse(text, targetTokens, model, fidelity) {
|
|
476
|
+
const sentences = _splitSentences(text).filter((s) => pyStrip(s) !== '');
|
|
477
|
+
if (sentences.length <= 1 || fidelity === 'lossless') {
|
|
478
|
+
// Nothing to rank, but still honor the budget (one long sentence, or lossless).
|
|
479
|
+
let small = text;
|
|
480
|
+
if (targetTokens !== null && tokens.count(small, model) > targetTokens) {
|
|
481
|
+
small = truncateToTokens(small, targetTokens, model);
|
|
482
|
+
}
|
|
483
|
+
return [small, { technique: 'extractive', kept: sentences.length, of: sentences.length }];
|
|
484
|
+
}
|
|
485
|
+
const freq = new Map();
|
|
486
|
+
for (const word of text.toLowerCase().match(WORD_RE) ?? []) {
|
|
487
|
+
if (!STOP.has(word))
|
|
488
|
+
freq.set(word, (freq.get(word) ?? 0) + 1);
|
|
489
|
+
}
|
|
490
|
+
// Length-normalized keyword mass: sum(freq) / sqrt(word count) — NOT the mean.
|
|
491
|
+
const score = (sentence) => {
|
|
492
|
+
const words = sentence.toLowerCase().match(WORD_RE) ?? [];
|
|
493
|
+
if (words.length === 0)
|
|
494
|
+
return 0;
|
|
495
|
+
let sum = 0;
|
|
496
|
+
for (const w of words)
|
|
497
|
+
sum += freq.get(w) ?? 0;
|
|
498
|
+
return sum / Math.sqrt(words.length);
|
|
499
|
+
};
|
|
500
|
+
const scores = sentences.map(score);
|
|
501
|
+
// indices ranked by descending score; stable (ties keep ascending original index).
|
|
502
|
+
const ranked = sentences.map((_, i) => i).sort((a, b) => scores[b] - scores[a] || a - b);
|
|
503
|
+
let keep;
|
|
504
|
+
if (targetTokens !== null) {
|
|
505
|
+
keep = new Set();
|
|
506
|
+
for (const i of ranked) {
|
|
507
|
+
const idxs = [...keep, i].sort((a, b) => a - b);
|
|
508
|
+
const trial = idxs.map((j) => sentences[j]).join(' ');
|
|
509
|
+
if (tokens.count(trial, model) > targetTokens && keep.size > 0)
|
|
510
|
+
break; // first always kept
|
|
511
|
+
keep.add(i);
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
else {
|
|
515
|
+
const divisor = fidelity === 'aggressive' ? 3 : 2; // aggressive: top third, balanced: top half
|
|
516
|
+
const n = Math.max(1, Math.floor(sentences.length / divisor));
|
|
517
|
+
keep = new Set(ranked.slice(0, n));
|
|
518
|
+
}
|
|
519
|
+
const keptIdx = [...keep].sort((a, b) => a - b);
|
|
520
|
+
let small = keptIdx.map((i) => sentences[i]).join(' ');
|
|
521
|
+
// The top-ranked sentence is always kept; truncate so targetTokens is never exceeded.
|
|
522
|
+
if (targetTokens !== null && tokens.count(small, model) > targetTokens) {
|
|
523
|
+
small = truncateToTokens(small, targetTokens, model);
|
|
524
|
+
}
|
|
525
|
+
return [small, { technique: 'extractive', kept: keep.size, of: sentences.length }];
|
|
526
|
+
}
|
|
527
|
+
/** Binary-search the longest prefix of `text` that fits `target` tokens (by code point). */
|
|
528
|
+
function truncateToTokens(text, target, model) {
|
|
529
|
+
if (target <= 0)
|
|
530
|
+
return '';
|
|
531
|
+
if (tokens.count(text, model) <= target)
|
|
532
|
+
return text;
|
|
533
|
+
const cps = Array.from(text); // slice by code point, matching Python str indexing
|
|
534
|
+
let lo = 0;
|
|
535
|
+
let hi = cps.length;
|
|
536
|
+
let best = '';
|
|
537
|
+
while (lo <= hi) {
|
|
538
|
+
const mid = (lo + hi) >> 1;
|
|
539
|
+
const cand = cps.slice(0, mid).join('');
|
|
540
|
+
if (tokens.count(cand, model) <= target) {
|
|
541
|
+
best = cand;
|
|
542
|
+
lo = mid + 1;
|
|
543
|
+
}
|
|
544
|
+
else {
|
|
545
|
+
hi = mid - 1;
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
return best;
|
|
549
|
+
}
|
|
550
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAa,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACxD,OAAO,EAAE,WAAW,EAAqB,MAAM,YAAY,CAAC;AAC5D,OAAO,EACL,YAAY,EACZ,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,WAAW,EACX,UAAU,GACX,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAQhE,MAAM,QAAQ,GAAwB,CAAC,UAAU,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC;AAC7E,MAAM,KAAK,GAAG,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,6CAA6C;AAEtF,oEAAoE;AACpE,MAAM,UAAW,SAAQ,KAAK;IAC5B,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;IAC3B,CAAC;CACF;AAED,SAAS,MAAM,CAAC,CAAS;IACvB,OAAO,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC;AAC9D,CAAC;AAED,0FAA0F;AAE1F,qGAAqG;AACrG,oEAAoE;AACpE,IAAI,OAAO,GAAiB,IAAI,WAAW,EAAE,CAAC;AAE9C;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAmB;IAC1C,MAAM,QAAQ,GAAG,OAAO,CAAC;IACzB,OAAO,GAAG,KAAK,CAAC;IAChB,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,4FAA4F;AAC5F,MAAM,UAAU,QAAQ;IACtB,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,SAAS,CAAC,CAAS;IAC1B,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC9D,CAAC;AAED,SAAS,KAAK,CAAC,QAAgB;IAC7B,MAAM,GAAG,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;IAChC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IAC3B,OAAO,GAAG,CAAC;AACb,CAAC;AAED,qFAAqF;AAErF,+EAA+E;AAC/E,MAAM,OAAO,MAAM;IAER;IACA;IACA;IACA;IAJT,YACS,EAAU,EACV,IAAY,EACZ,WAAmB,EACnB,aAAsC,EAAE;QAHxC,OAAE,GAAF,EAAE,CAAQ;QACV,SAAI,GAAJ,IAAI,CAAQ;QACZ,gBAAW,GAAX,WAAW,CAAQ;QACnB,eAAU,GAAV,UAAU,CAA8B;IAC9C,CAAC;IAEJ,gFAAgF;IAChF,MAAM;QACJ,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACvC,CAAC;IAED,sFAAsF;IACtF,IAAI,SAAS;QACX,MAAM,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;QACpC,OAAO,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACxD,CAAC;IAED,qFAAqF;IACrF,MAAM;QACJ,OAAO;YACL,EAAE,EAAE,IAAI,CAAC,EAAE;YACX,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,YAAY,EAAE,IAAI,CAAC,WAAW;YAC9B,WAAW,EAAE,EAAE,GAAG,IAAI,CAAC,UAAU,EAAE;SACpC,CAAC;IACJ,CAAC;IAED,sFAAsF;IACtF,MAAM,CAAC,QAAQ,CAAC,IAA6B;QAC3C,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE;YAC/E,GAAG,CAAE,IAAI,CAAC,WAAmD,IAAI,EAAE,CAAC;SACrE,CAAC,CAAC;IACL,CAAC;CACF;AAED,wFAAwF;AAExF,MAAM,MAAM,GACV,yFAAyF,CAAC;AAC5F,MAAM,QAAQ,GAAG,4DAA4D,CAAC;AAC9E,MAAM,MAAM,GAAG,iDAAiD,CAAC;AACjE,MAAM,OAAO,GAAG,4CAA4C,CAAC;AAC7D,MAAM,OAAO,GAAG,YAAY,CAAC;AAE7B,wFAAwF;AACxF,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AACtC,MAAM,OAAO,GAAG,IAAI,MAAM,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;AAC1C,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AACtC,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;AACxC,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;AACxC,MAAM,SAAS,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC;AACrC,MAAM,QAAQ,GAAG,4DAA4D,CAAC;AAE9E,MAAM,YAAY,GAAG;IACnB,MAAM;IACN,QAAQ;IACR,WAAW;IACX,OAAO;IACP,SAAS;IACT,OAAO;IACP,SAAS;IACT,QAAQ;IACR,MAAM;IACN,MAAM;IACN,SAAS;IACT,UAAU;IACV,UAAU;IACV,IAAI;IACJ,IAAI;CACL,CAAC;AAEF,2FAA2F;AAC3F,MAAM,cAAc,GAClB,0FAA0F,CAAC;AAE7F,2EAA2E;AAC3E,MAAM,UAAU,MAAM,CAAC,OAAe;IACpC,MAAM,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3B,IAAI,CAAC,KAAK,EAAE;QAAE,OAAO,OAAO,CAAC;IAC7B,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAChB,IAAI,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;QAC7B,IAAI,CAAC;YACH,SAAS,CAAC,CAAC,CAAC,CAAC;YACb,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,MAAM,CAAC;YACP,0BAA0B;QAC5B,CAAC;IACH,CAAC;IACD,IAAI,aAAa,CAAC,CAAC,CAAC;QAAE,OAAO,MAAM,CAAC;IACpC,IAAI,aAAa,CAAC,CAAC,CAAC;QAAE,OAAO,MAAM,CAAC;IACpC,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,aAAa,CAAC,CAAS;IAC9B,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC;AAC1D,CAAC;AAED,SAAS,aAAa,CAAC,CAAS;IAC9B,MAAM,KAAK,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;IAC/B,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IACnC,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,MAAM,EAAE,IAAI,KAAK;QAAE,IAAI,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YAAE,IAAI,EAAE,CAAC;IAC5E,OAAO,IAAI,IAAI,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC;AACpC,CAAC;AAED,SAAS,aAAa,CAAC,CAAS;IAC9B,MAAM,KAAK,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;IAC/B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACrC,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,MAAM,EAAE,IAAI,KAAK,EAAE,CAAC;QACvB,MAAM,EAAE,GAAG,OAAO,CAAC,EAAE,CAAC,CAAC;QACvB,MAAM,WAAW,GACf,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC/E,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,WAAW;YAAE,IAAI,EAAE,CAAC;IACtE,CAAC;IACD,OAAO,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC;AACjD,CAAC;AAYD;;;;;;;GAOG;AACH,MAAM,UAAU,QAAQ,CAAC,OAAgB,EAAE,OAAwB,EAAE;IACnE,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,UAAU,CAAC;IAC7C,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC;IAC/C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,QAAQ,CAAC;IACrC,IAAI,IAAI,GAAW,IAAI,CAAC,IAAI,IAAI,MAAM,CAAC;IAEvC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,UAAU,CAClB,uEAAuE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,CAClG,CAAC;IACJ,CAAC;IAED,IAAI,QAAgB,CAAC;IACrB,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAChC,QAAQ,GAAG,OAAO,CAAC;IACrB,CAAC;SAAM,CAAC;QACN,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC;QAC1B,IAAI,IAAI,KAAK,MAAM;YAAE,IAAI,GAAG,MAAM,CAAC;IACrC,CAAC;IAED,IAAI,IAAI,KAAK,MAAM;QAAE,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;IAE7C,IAAI,KAAa,CAAC;IAClB,IAAI,UAAmC,CAAC;IACxC,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,CAAC,KAAK,EAAE,UAAU,CAAC,GAAG,YAAY,CAAC,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;IAC9E,CAAC;SAAM,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QAC3B,CAAC,KAAK,EAAE,UAAU,CAAC,GAAG,YAAY,CAAC,QAAQ,EAAE,YAAY,EAAE,KAAK,CAAC,CAAC;IACpE,CAAC;SAAM,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QAC3B,CAAC,KAAK,EAAE,UAAU,CAAC,GAAG,YAAY,CAAC,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;IAC9E,CAAC;SAAM,CAAC;QACN,CAAC,KAAK,EAAE,UAAU,CAAC,GAAG,aAAa,CAAC,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;IAC/E,CAAC;IAED,MAAM,GAAG,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC5B,mGAAmG;IACnG,kGAAkG;IAClG,MAAM,SAAS,GAAG,UAAU,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IACzF,MAAM,EAAE,GAAG,SAAS,CAAC,GAAG,GAAG,IAAI,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACzD,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC;IACrD,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;AACzB,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,UAAU,CAAC,MAAc;IACvC,OAAO,MAAM,CAAC,MAAM,EAAE,CAAC;AACzB,CAAC;AAUD,qGAAqG;AACrG,MAAM,OAAO,iBAAiB;IAC5B,QAAQ,CAAC,OAAgB,EAAE,OAA0B,EAAE;QACrD,OAAO,QAAQ,CAAC,OAAO,EAAE;YACvB,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,MAAM;YACzB,YAAY,EAAE,IAAI,CAAC,YAAY,IAAI,IAAI;YACvC,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,QAAQ;YAC7B,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,UAAU;SACtC,CAAC,CAAC;IACL,CAAC;CACF;AAED,0FAA0F;AAE1F,SAAS,UAAU,CAAC,GAAS;IAC3B,IAAI,GAAG,YAAY,GAAG,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,IAAI,GAAG,EAAgB,CAAC;QACpC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,GAAG;YAAE,IAAI,CAAC,KAAK,IAAI;gBAAE,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;QACpE,OAAO,GAAG,CAAC;IACb,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;QAAE,OAAO,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACnD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,mFAAmF;AACnF,SAAS,KAAK,CAAC,CAAS;IACtB,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,KAAK,MAAM,CAAC,IAAI,CAAC;QAAE,CAAC,EAAE,CAAC;IACvB,OAAO,CAAC,CAAC;AACX,CAAC;AAED,SAAS,OAAO,CAAC,GAAS,EAAE,MAAc,EAAE,KAAa;IACvD,IAAI,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;IACvB,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,MAAM;QAAE,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAEhE,IAAI,GAAG,YAAY,GAAG,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QAC1B,yFAAyF;QACzF,MAAM,SAAS,GAAG,CAAC,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;YACjD,CAAC;YACD,GAAG;YACH,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAS,CAAC,CAAC;SACtC,CAAC,CAAC,CAAC;QACJ,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;QACzD,KAAK,MAAM,EAAE,CAAC,EAAE,IAAI,SAAS,EAAE,CAAC;YAC9B,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,IAAI,MAAM;gBAAE,MAAM;YACtD,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACjB,CAAC;QACD,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;QACpB,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,MAAM;YAAE,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACjE,CAAC;SAAM,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAC9B,MAAM,QAAQ,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC;QAC1B,OAAO,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM;YAAE,QAAQ,CAAC,GAAG,EAAE,CAAC;QAC5F,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC;QACxB,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,MAAM;YAAE,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACjE,CAAC;IAED,oFAAoF;IACpF,OAAO,CAAC,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;AACxD,CAAC;AAED,SAAS,YAAY,CACnB,IAAY,EACZ,YAA2B,EAC3B,KAAa,EACb,QAAkB;IAElB,IAAI,GAAS,CAAC;IACd,IAAI,CAAC;QACH,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,aAAa,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;IAC9D,CAAC;IACD,MAAM,MAAM,GAAG,QAAQ,KAAK,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IAC/D,IAAI,SAAS,GAAG,QAAQ,KAAK,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,kBAAkB,CAAC;IACxE,IAAI,YAAY,KAAK,IAAI;QAAE,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;IACjE,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,CAAC,CAAC;IAC9D,IAAI,OAAO;QAAE,SAAS,IAAI,OAAO,CAAC;IAClC,OAAO,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;AAChC,CAAC;AAED,SAAS,YAAY,CACnB,IAAY,EACZ,YAA2B,EAC3B,KAAa,EACb,QAAkB;IAElB,IAAI,IAAI,GAAG,IAAI,CAAC;IAChB,IAAI,QAAQ,KAAK,UAAU;QAAE,IAAI,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IACxD,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,IAAI,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;QACzB,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE;YAAE,SAAS;QACnC,IAAI,QAAQ,KAAK,YAAY,EAAE,CAAC;YAC9B,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;YAChC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;YAC5D,IAAI,GAAG,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;QACtD,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC;IACD,IAAI,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3B,IAAI,YAAY,KAAK,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,YAAY,EAAE,CAAC;QACvE,KAAK,GAAG,gBAAgB,CAAC,KAAK,EAAE,YAAY,EAAE,KAAK,CAAC,CAAC;IACvD,CAAC;IACD,OAAO,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,QAAQ,QAAQ,EAAE,EAAE,CAAC,CAAC;AACpD,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAY;IACpC,IAAI,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IACtC,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IACrC,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IACjC,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,OAAO,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AACpC,CAAC;AAED,SAAS,YAAY,CACnB,IAAY,EACZ,YAA2B,EAC3B,KAAa;IAEb,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACzC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,IAAI,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;QACpC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxC,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAChD,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC3C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAW,CAAC;QACrC,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC9D,CAAC;IAED,IAAI,IAAc,CAAC;IACnB,IAAI,YAAY,KAAK,IAAI,EAAE,CAAC;QAC1B,IAAI,GAAG,KAAK,CAAC;IACf,CAAC;SAAM,CAAC;QACN,MAAM,MAAM,GAAG,IAAI,GAAG,EAAU,CAAC;QACjC,IAAI,OAAO,GAAG,CAAC,CAAC;QAChB,+DAA+D;QAC/D,MAAM,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAW,EAAE,CAAC,CAAC,CAAC;QAC3F,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;QACrD,KAAK,MAAM,EAAE,IAAI,EAAE,IAAI,SAAS,EAAE,CAAC;YACjC,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAW,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,uBAAuB;YAC3F,IAAI,OAAO,GAAG,IAAI,GAAG,YAAY,IAAI,MAAM,CAAC,IAAI,GAAG,CAAC;gBAAE,MAAM,CAAC,4BAA4B;YACzF,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACjB,OAAO,IAAI,IAAI,CAAC;QAClB,CAAC;QACD,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,8BAA8B;IACjF,CAAC;IAED,IAAI,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAW,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACxE,IAAI,YAAY,KAAK,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,YAAY,EAAE,CAAC;QACvE,KAAK,GAAG,gBAAgB,CAAC,KAAK,EAAE,YAAY,EAAE,KAAK,CAAC,CAAC;IACvD,CAAC;IACD,OAAO,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,iBAAiB,EAAE,QAAQ,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;AAC3E,CAAC;AAED,SAAS,aAAa,CAAC,IAAY;IACjC,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;IACtB,IAAI,KAAK,GAAkB,IAAI,CAAC;IAChC,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,IAAI,WAAW,GAAG,IAAI,CAAC,CAAC,iDAAiD;IACzE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACb,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,CAAW,CAAC;QAC7B,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAE,IAAI,CAAC,CAAC,GAAG,CAAC,CAAY,CAAC,CAAC,CAAC,EAAE,CAAC;QACrD,IAAI,OAAO,EAAE,CAAC;YACZ,IAAI,EAAE,KAAK,GAAG,IAAI,GAAG,KAAK,GAAG,EAAE,CAAC;gBAC9B,OAAO,GAAG,KAAK,CAAC;gBAChB,CAAC,IAAI,CAAC,CAAC;YACT,CAAC;iBAAM,CAAC;gBACN,IAAI,EAAE,KAAK,IAAI;oBAAE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,0CAA0C;gBAC3E,CAAC,IAAI,CAAC,CAAC;YACT,CAAC;YACD,SAAS;QACX,CAAC;QACD,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACnB,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACb,IAAI,EAAE,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC7B,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,0CAA0C;gBACzD,CAAC,IAAI,CAAC,CAAC;gBACP,SAAS;YACX,CAAC;YACD,IAAI,EAAE,KAAK,KAAK;gBAAE,KAAK,GAAG,IAAI,CAAC;YAC/B,CAAC,IAAI,CAAC,CAAC;YACP,SAAS;QACX,CAAC;QACD,IAAI,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YAC3C,KAAK,GAAG,EAAE,CAAC;YACX,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACb,WAAW,GAAG,KAAK,CAAC;YACpB,CAAC,IAAI,CAAC,CAAC;YACP,SAAS;QACX,CAAC;QACD,IAAI,EAAE,KAAK,GAAG,IAAI,GAAG,KAAK,GAAG,EAAE,CAAC;YAC9B,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI;gBAAE,CAAC,IAAI,CAAC,CAAC;YACzC,SAAS;QACX,CAAC;QACD,IAAI,EAAE,KAAK,GAAG,IAAI,GAAG,KAAK,GAAG,EAAE,CAAC;YAC9B,OAAO,GAAG,IAAI,CAAC;YACf,CAAC,IAAI,CAAC,CAAC;YACP,SAAS;QACX,CAAC;QACD,IAAI,EAAE,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,WAAW,IAAI,GAAG,KAAK,GAAG,CAAC,IAAI,YAAY,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3E,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI;gBAAE,CAAC,IAAI,CAAC,CAAC;YACzC,SAAS;QACX,CAAC;QACD,IAAI,EAAE,KAAK,IAAI;YAAE,WAAW,GAAG,IAAI,CAAC;aAC/B,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;YAAE,WAAW,GAAG,KAAK,CAAC;QAC7C,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACb,CAAC,IAAI,CAAC,CAAC;IACT,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACtB,CAAC;AAED,SAAS,YAAY,CAAC,IAAY,EAAE,CAAS;IAC3C,cAAc,CAAC,SAAS,GAAG,CAAC,CAAC;IAC7B,OAAO,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,OAAO,GAAG,eAAe,CAAC;AAChC,MAAM,YAAY,GAAG,6BAA6B,CAAC;AACnD,MAAM,OAAO,GAAG,aAAa,CAAC;AAC9B,MAAM,IAAI,GAAG,IAAI,GAAG,CAClB,wFAAwF,CAAC,KAAK,CAC5F,GAAG,CACJ,CACF,CAAC;AACF,iGAAiG;AACjG,wDAAwD;AACxD,MAAM,MAAM,GAAG,IAAI,GAAG,CACpB,yFAAyF,CAAC,KAAK,CAC7F,GAAG,CACJ,CACF,CAAC;AAEF,4FAA4F;AAC5F,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QAChD,IAAI,IAAI,KAAK,EAAE;YAAE,SAAS;QAC1B,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACnB,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAW,CAAC;YAC3C,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;YACnC,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAW,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACrE,MAAM,OAAO,GAAG,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;YACjD,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YACnC,MAAM,UAAU,GAAG,QAAQ,KAAK,EAAE,IAAI,YAAY,CAAC,QAAQ,CAAC,CAAC;YAC7D,IAAI,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,UAAU,EAAE,CAAC;gBACnC,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC;gBACxC,SAAS;YACX,CAAC;QACH,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC;IACD,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;AAC9C,CAAC;AAED,SAAS,aAAa,CACpB,IAAY,EACZ,YAA2B,EAC3B,KAAa,EACb,QAAkB;IAElB,MAAM,SAAS,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;IACzE,IAAI,SAAS,CAAC,MAAM,IAAI,CAAC,IAAI,QAAQ,KAAK,UAAU,EAAE,CAAC;QACrD,gFAAgF;QAChF,IAAI,KAAK,GAAG,IAAI,CAAC;QACjB,IAAI,YAAY,KAAK,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,YAAY,EAAE,CAAC;YACvE,KAAK,GAAG,gBAAgB,CAAC,KAAK,EAAE,YAAY,EAAE,KAAK,CAAC,CAAC;QACvD,CAAC;QACD,OAAO,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,YAAY,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,EAAE,EAAE,EAAE,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;IAC5F,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,GAAG,EAAkB,CAAC;IACvC,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;QAC3D,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACjE,CAAC;IAED,+EAA+E;IAC/E,MAAM,KAAK,GAAG,CAAC,QAAgB,EAAU,EAAE;QACzC,MAAM,KAAK,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QAC1D,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,CAAC,CAAC;QACjC,IAAI,GAAG,GAAG,CAAC,CAAC;QACZ,KAAK,MAAM,CAAC,IAAI,KAAK;YAAE,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC/C,OAAO,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACvC,CAAC,CAAC;IAEF,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACpC,mFAAmF;IACnF,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAE,GAAG,MAAM,CAAC,CAAC,CAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAE3F,IAAI,IAAiB,CAAC;IACtB,IAAI,YAAY,KAAK,IAAI,EAAE,CAAC;QAC1B,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;QACzB,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;YACvB,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAChD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,CAAW,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAChE,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,YAAY,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC;gBAAE,MAAM,CAAC,oBAAoB;YAC3F,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACd,CAAC;IACH,CAAC;SAAM,CAAC;QACN,MAAM,OAAO,GAAG,QAAQ,KAAK,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,4CAA4C;QAC/F,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;QAC9D,IAAI,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACrC,CAAC;IAED,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAChD,IAAI,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,CAAW,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACjE,sFAAsF;IACtF,IAAI,YAAY,KAAK,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,YAAY,EAAE,CAAC;QACvE,KAAK,GAAG,gBAAgB,CAAC,KAAK,EAAE,YAAY,EAAE,KAAK,CAAC,CAAC;IACvD,CAAC;IACD,OAAO,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,YAAY,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;AACrF,CAAC;AAED,4FAA4F;AAC5F,SAAS,gBAAgB,CAAC,IAAY,EAAE,MAAc,EAAE,KAAa;IACnE,IAAI,MAAM,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IAC3B,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM;QAAE,OAAO,IAAI,CAAC;IACrD,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,oDAAoD;IAClF,IAAI,EAAE,GAAG,CAAC,CAAC;IACX,IAAI,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC;IACpB,IAAI,IAAI,GAAG,EAAE,CAAC;IACd,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC;QAChB,MAAM,GAAG,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;QAC3B,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACxC,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,EAAE,CAAC;YACxC,IAAI,GAAG,IAAI,CAAC;YACZ,EAAE,GAAG,GAAG,GAAG,CAAC,CAAC;QACf,CAAC;aAAM,CAAC;YACN,EAAE,GAAG,GAAG,GAAG,CAAC,CAAC;QACf,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
package/dist/json.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A tiny order-preserving JSON parser + a serializer that mirrors Python's
|
|
3
|
+
* `json.dumps(obj, ensure_ascii=False, separators=(",", ":"))` as closely as practical.
|
|
4
|
+
*
|
|
5
|
+
* Why not `JSON.parse` / `JSON.stringify`? Three Python behaviors must be reproduced for byte-close
|
|
6
|
+
* output: (1) object key order is document order (JS objects reorder integer-like keys, so parsed
|
|
7
|
+
* objects are `Map`s here); (2) duplicate keys keep the last value; (3) an integer-valued *float*
|
|
8
|
+
* literal (`1.0`, `1e5`) serializes with a trailing `.0` (`"1.0"`, `"100000.0"`) where JS would emit
|
|
9
|
+
* `"1"`. Numbers are therefore carried as raw source tokens (`JNum`). String escaping already matches
|
|
10
|
+
* (`JSON.stringify` of a string == Python `ensure_ascii=False` for the C0 range, `"`, and `\\`).
|
|
11
|
+
*
|
|
12
|
+
* Reversibility never depends on this: `expand()` returns the stored original verbatim.
|
|
13
|
+
*/
|
|
14
|
+
/** A JSON number carried as its raw source token, so int/float formatting round-trips. */
|
|
15
|
+
export declare class JNum {
|
|
16
|
+
readonly raw: string;
|
|
17
|
+
constructor(raw: string);
|
|
18
|
+
}
|
|
19
|
+
/** The parsed-JSON value tree. Objects are `Map` (ordered), arrays are arrays, numbers are `JNum`. */
|
|
20
|
+
export type JVal = null | boolean | string | JNum | JVal[] | Map<string, JVal>;
|
|
21
|
+
/** Parse standard JSON into the ordered `JVal` tree. Throws `SyntaxError` on invalid input. */
|
|
22
|
+
export declare function parseJson(text: string): JVal;
|
|
23
|
+
/**
|
|
24
|
+
* Serialize a value the way Python's compact `json.dumps` would. Accepts both the parsed `JVal` tree
|
|
25
|
+
* (`Map`/`JNum`) and plain JS values (used for object input, where numbers are plain `number`).
|
|
26
|
+
*/
|
|
27
|
+
export declare function dumps(v: unknown): string;
|
|
28
|
+
//# sourceMappingURL=json.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.d.ts","sourceRoot":"","sources":["../src/json.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,0FAA0F;AAC1F,qBAAa,IAAI;aACa,GAAG,EAAE,MAAM;gBAAX,GAAG,EAAE,MAAM;CACxC;AAED,sGAAsG;AACtG,MAAM,MAAM,IAAI,GAAG,IAAI,GAAG,OAAO,GAAG,MAAM,GAAG,IAAI,GAAG,IAAI,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AAuK/E,+FAA+F;AAC/F,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAE5C;AAaD;;;GAGG;AACH,wBAAgB,KAAK,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CAyBxC"}
|