toon-formatter 2.2.1 → 2.3.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/CHANGELOG.md +19 -0
- package/README.md +58 -0
- package/package.json +1 -1
- package/src/constants.js +142 -0
- package/src/csv_formatter/index.js +49 -24
- package/src/index.js +27 -13
- package/src/json_formatter/index.js +49 -24
- package/src/utils.js +302 -0
- package/src/xml_formatter/index.js +49 -24
- package/src/yaml_formatter/index.js +25 -13
|
@@ -7,6 +7,7 @@ import { yamlToJson, yamlToJsonSync, jsonToYaml, jsonToYamlSync } from './yaml.j
|
|
|
7
7
|
import { xmlToJson, xmlToJsonSync, jsonToXml, jsonToXmlSync } from './xml.js';
|
|
8
8
|
import { csvToJson, csvToJsonSync, jsonToCsv, jsonToCsvSync } from './csv.js';
|
|
9
9
|
import { validateJsonString, validateJsonStringSync } from './validator.js';
|
|
10
|
+
import { dataManager, dataManagerAsync, extractJsonFromString, extractXmlFromString, extractCsvFromString } from '../utils.js';
|
|
10
11
|
|
|
11
12
|
export class JsonConverter {
|
|
12
13
|
/**
|
|
@@ -110,8 +111,9 @@ export class JsonConverter {
|
|
|
110
111
|
*/
|
|
111
112
|
toToon(jsonData, options = {}) {
|
|
112
113
|
const { conversionMode = 'no_encryption' } = options;
|
|
114
|
+
const optimizedConverterFn = dataManager(jsonToToonSync, extractJsonFromString);
|
|
113
115
|
return this._convertWithEncryption(
|
|
114
|
-
(data) =>
|
|
116
|
+
(data) => optimizedConverterFn(data),
|
|
115
117
|
jsonData,
|
|
116
118
|
conversionMode
|
|
117
119
|
);
|
|
@@ -126,8 +128,9 @@ export class JsonConverter {
|
|
|
126
128
|
*/
|
|
127
129
|
async toToonAsync(jsonData, options = {}) {
|
|
128
130
|
const { conversionMode = 'no_encryption' } = options;
|
|
131
|
+
const optimizedConverterFn = dataManagerAsync(jsonToToon, extractJsonFromString);
|
|
129
132
|
return this._convertWithEncryptionAsync(
|
|
130
|
-
async (data) =>
|
|
133
|
+
async (data) => optimizedConverterFn(data),
|
|
131
134
|
jsonData,
|
|
132
135
|
conversionMode
|
|
133
136
|
);
|
|
@@ -178,8 +181,9 @@ export class JsonConverter {
|
|
|
178
181
|
*/
|
|
179
182
|
toYaml(jsonData, options = {}) {
|
|
180
183
|
const { conversionMode = 'no_encryption' } = options;
|
|
184
|
+
const optimizedConverterFn = dataManager(jsonToYamlSync, extractJsonFromString);
|
|
181
185
|
return this._convertWithEncryption(
|
|
182
|
-
(data) =>
|
|
186
|
+
(data) => optimizedConverterFn(data),
|
|
183
187
|
jsonData,
|
|
184
188
|
conversionMode
|
|
185
189
|
);
|
|
@@ -194,8 +198,9 @@ export class JsonConverter {
|
|
|
194
198
|
*/
|
|
195
199
|
async toYamlAsync(jsonData, options = {}) {
|
|
196
200
|
const { conversionMode = 'no_encryption' } = options;
|
|
201
|
+
const optimizedConverterFn = dataManagerAsync(jsonToYaml, extractJsonFromString);
|
|
197
202
|
return this._convertWithEncryptionAsync(
|
|
198
|
-
async (data) =>
|
|
203
|
+
async (data) => optimizedConverterFn(data),
|
|
199
204
|
jsonData,
|
|
200
205
|
conversionMode
|
|
201
206
|
);
|
|
@@ -212,8 +217,9 @@ export class JsonConverter {
|
|
|
212
217
|
*/
|
|
213
218
|
fromXml(xmlString, options = {}) {
|
|
214
219
|
const { conversionMode = 'no_encryption' } = options;
|
|
220
|
+
const optimizedConverterFn = dataManager(xmlToJsonSync, extractXmlFromString);
|
|
215
221
|
return this._convertWithEncryption(
|
|
216
|
-
(data) =>
|
|
222
|
+
(data) => optimizedConverterFn(data),
|
|
217
223
|
xmlString,
|
|
218
224
|
conversionMode
|
|
219
225
|
);
|
|
@@ -228,8 +234,9 @@ export class JsonConverter {
|
|
|
228
234
|
*/
|
|
229
235
|
async fromXmlAsync(xmlString, options = {}) {
|
|
230
236
|
const { conversionMode = 'no_encryption' } = options;
|
|
237
|
+
const optimizedConverterFn = dataManagerAsync(xmlToJson, extractXmlFromString);
|
|
231
238
|
return this._convertWithEncryptionAsync(
|
|
232
|
-
async (data) =>
|
|
239
|
+
async (data) => optimizedConverterFn(data),
|
|
233
240
|
xmlString,
|
|
234
241
|
conversionMode
|
|
235
242
|
);
|
|
@@ -244,8 +251,9 @@ export class JsonConverter {
|
|
|
244
251
|
*/
|
|
245
252
|
toXml(jsonData, options = {}) {
|
|
246
253
|
const { conversionMode = 'no_encryption' } = options;
|
|
254
|
+
const optimizedConverterFn = dataManager(jsonToXmlSync, extractJsonFromString);
|
|
247
255
|
return this._convertWithEncryption(
|
|
248
|
-
(data) =>
|
|
256
|
+
(data) => optimizedConverterFn(data),
|
|
249
257
|
jsonData,
|
|
250
258
|
conversionMode
|
|
251
259
|
);
|
|
@@ -260,8 +268,9 @@ export class JsonConverter {
|
|
|
260
268
|
*/
|
|
261
269
|
async toXmlAsync(jsonData, options = {}) {
|
|
262
270
|
const { conversionMode = 'no_encryption' } = options;
|
|
271
|
+
const optimizedConverterFn = dataManagerAsync(jsonToXml, extractJsonFromString);
|
|
263
272
|
return this._convertWithEncryptionAsync(
|
|
264
|
-
async (data) =>
|
|
273
|
+
async (data) => optimizedConverterFn(data),
|
|
265
274
|
jsonData,
|
|
266
275
|
conversionMode
|
|
267
276
|
);
|
|
@@ -278,8 +287,9 @@ export class JsonConverter {
|
|
|
278
287
|
*/
|
|
279
288
|
fromCsv(csvString, options = {}) {
|
|
280
289
|
const { conversionMode = 'no_encryption' } = options;
|
|
290
|
+
const optimizedConverterFn = dataManager(csvToJsonSync, extractCsvFromString);
|
|
281
291
|
return this._convertWithEncryption(
|
|
282
|
-
(data) =>
|
|
292
|
+
(data) => optimizedConverterFn(data),
|
|
283
293
|
csvString,
|
|
284
294
|
conversionMode
|
|
285
295
|
);
|
|
@@ -294,8 +304,9 @@ export class JsonConverter {
|
|
|
294
304
|
*/
|
|
295
305
|
async fromCsvAsync(csvString, options = {}) {
|
|
296
306
|
const { conversionMode = 'no_encryption' } = options;
|
|
307
|
+
const optimizedConverterFn = dataManagerAsync(csvToJson, extractCsvFromString);
|
|
297
308
|
return this._convertWithEncryptionAsync(
|
|
298
|
-
async (data) =>
|
|
309
|
+
async (data) => optimizedConverterFn(data),
|
|
299
310
|
csvString,
|
|
300
311
|
conversionMode
|
|
301
312
|
);
|
|
@@ -310,8 +321,9 @@ export class JsonConverter {
|
|
|
310
321
|
*/
|
|
311
322
|
toCsv(jsonData, options = {}) {
|
|
312
323
|
const { conversionMode = 'no_encryption' } = options;
|
|
324
|
+
const optimizedConverterFn = dataManager(jsonToCsvSync, extractJsonFromString);
|
|
313
325
|
return this._convertWithEncryption(
|
|
314
|
-
(data) =>
|
|
326
|
+
(data) => optimizedConverterFn(data),
|
|
315
327
|
jsonData,
|
|
316
328
|
conversionMode
|
|
317
329
|
);
|
|
@@ -326,8 +338,9 @@ export class JsonConverter {
|
|
|
326
338
|
*/
|
|
327
339
|
async toCsvAsync(jsonData, options = {}) {
|
|
328
340
|
const { conversionMode = 'no_encryption' } = options;
|
|
341
|
+
const optimizedConverterFn = dataManagerAsync(jsonToCsv, extractJsonFromString);
|
|
329
342
|
return this._convertWithEncryptionAsync(
|
|
330
|
-
async (data) =>
|
|
343
|
+
async (data) => optimizedConverterFn(data),
|
|
331
344
|
jsonData,
|
|
332
345
|
conversionMode
|
|
333
346
|
);
|
|
@@ -383,7 +396,8 @@ export class JsonConverter {
|
|
|
383
396
|
* @returns {string} TOON formatted string
|
|
384
397
|
*/
|
|
385
398
|
static toToon(jsonData) {
|
|
386
|
-
|
|
399
|
+
const optimizedConverterFn = dataManager(jsonToToonSync, extractJsonFromString);
|
|
400
|
+
return optimizedConverterFn(jsonData);
|
|
387
401
|
}
|
|
388
402
|
|
|
389
403
|
/**
|
|
@@ -392,7 +406,8 @@ export class JsonConverter {
|
|
|
392
406
|
* @returns {Promise<string>} TOON formatted string
|
|
393
407
|
*/
|
|
394
408
|
static async toToonAsync(jsonData) {
|
|
395
|
-
|
|
409
|
+
const optimizedConverterFn = dataManagerAsync(jsonToToon, extractJsonFromString);
|
|
410
|
+
return optimizedConverterFn(jsonData);
|
|
396
411
|
}
|
|
397
412
|
|
|
398
413
|
/**
|
|
@@ -421,7 +436,8 @@ export class JsonConverter {
|
|
|
421
436
|
* @returns {string} YAML formatted string
|
|
422
437
|
*/
|
|
423
438
|
static toYaml(jsonData) {
|
|
424
|
-
|
|
439
|
+
const optimizedConverterFn = dataManager(jsonToYamlSync, extractJsonFromString);
|
|
440
|
+
return optimizedConverterFn(jsonData);
|
|
425
441
|
}
|
|
426
442
|
|
|
427
443
|
/**
|
|
@@ -430,7 +446,8 @@ export class JsonConverter {
|
|
|
430
446
|
* @returns {Promise<string>} YAML formatted string
|
|
431
447
|
*/
|
|
432
448
|
static async toYamlAsync(jsonData) {
|
|
433
|
-
|
|
449
|
+
const optimizedConverterFn = dataManagerAsync(jsonToYaml, extractJsonFromString);
|
|
450
|
+
return optimizedConverterFn(jsonData);
|
|
434
451
|
}
|
|
435
452
|
|
|
436
453
|
/**
|
|
@@ -439,7 +456,8 @@ export class JsonConverter {
|
|
|
439
456
|
* @returns {Object|string} JSON object or string
|
|
440
457
|
*/
|
|
441
458
|
static fromXml(xmlString) {
|
|
442
|
-
|
|
459
|
+
const optimizedConverterFn = dataManager(xmlToJsonSync, extractXmlFromString);
|
|
460
|
+
return optimizedConverterFn(xmlString);
|
|
443
461
|
}
|
|
444
462
|
|
|
445
463
|
/**
|
|
@@ -448,7 +466,8 @@ export class JsonConverter {
|
|
|
448
466
|
* @returns {Promise<Object|string>} JSON object or string
|
|
449
467
|
*/
|
|
450
468
|
static async fromXmlAsync(xmlString) {
|
|
451
|
-
|
|
469
|
+
const optimizedConverterFn = dataManagerAsync(xmlToJson, extractXmlFromString);
|
|
470
|
+
return optimizedConverterFn(xmlString);
|
|
452
471
|
}
|
|
453
472
|
|
|
454
473
|
/**
|
|
@@ -457,7 +476,8 @@ export class JsonConverter {
|
|
|
457
476
|
* @returns {string} XML formatted string
|
|
458
477
|
*/
|
|
459
478
|
static toXml(jsonData) {
|
|
460
|
-
|
|
479
|
+
const optimizedConverterFn = dataManager(jsonToXmlSync, extractJsonFromString);
|
|
480
|
+
return optimizedConverterFn(jsonData);
|
|
461
481
|
}
|
|
462
482
|
|
|
463
483
|
/**
|
|
@@ -466,7 +486,8 @@ export class JsonConverter {
|
|
|
466
486
|
* @returns {Promise<string>} XML formatted string
|
|
467
487
|
*/
|
|
468
488
|
static async toXmlAsync(jsonData) {
|
|
469
|
-
|
|
489
|
+
const optimizedConverterFn = dataManagerAsync(jsonToXml, extractJsonFromString);
|
|
490
|
+
return optimizedConverterFn(jsonData);
|
|
470
491
|
}
|
|
471
492
|
|
|
472
493
|
/**
|
|
@@ -475,7 +496,8 @@ export class JsonConverter {
|
|
|
475
496
|
* @returns {Array<Object>|string} JSON object or string
|
|
476
497
|
*/
|
|
477
498
|
static fromCsv(csvString) {
|
|
478
|
-
|
|
499
|
+
const optimizedConverterFn = dataManager(csvToJsonSync, extractCsvFromString);
|
|
500
|
+
return optimizedConverterFn(csvString);
|
|
479
501
|
}
|
|
480
502
|
|
|
481
503
|
/**
|
|
@@ -484,7 +506,8 @@ export class JsonConverter {
|
|
|
484
506
|
* @returns {Promise<Array<Object>|string>} JSON object or string
|
|
485
507
|
*/
|
|
486
508
|
static async fromCsvAsync(csvString) {
|
|
487
|
-
|
|
509
|
+
const optimizedConverterFn = dataManagerAsync(csvToJson, extractCsvFromString);
|
|
510
|
+
return optimizedConverterFn(csvString);
|
|
488
511
|
}
|
|
489
512
|
|
|
490
513
|
/**
|
|
@@ -493,7 +516,8 @@ export class JsonConverter {
|
|
|
493
516
|
* @returns {string} CSV formatted string
|
|
494
517
|
*/
|
|
495
518
|
static toCsv(jsonData) {
|
|
496
|
-
|
|
519
|
+
const optimizedConverterFn = dataManager(jsonToCsvSync, extractJsonFromString);
|
|
520
|
+
return optimizedConverterFn(jsonData);
|
|
497
521
|
}
|
|
498
522
|
|
|
499
523
|
/**
|
|
@@ -502,7 +526,8 @@ export class JsonConverter {
|
|
|
502
526
|
* @returns {Promise<string>} CSV formatted string
|
|
503
527
|
*/
|
|
504
528
|
static async toCsvAsync(jsonData) {
|
|
505
|
-
|
|
529
|
+
const optimizedConverterFn = dataManagerAsync(jsonToCsv, extractJsonFromString);
|
|
530
|
+
return await optimizedConverterFn(jsonData);
|
|
506
531
|
}
|
|
507
532
|
|
|
508
533
|
/**
|
package/src/utils.js
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
* Utility functions for TOON conversion
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
import { EXPENSIVE_WORDS } from './constants.js';
|
|
6
|
+
|
|
5
7
|
/**
|
|
6
8
|
* Encodes XML reserved characters to prevent parsing errors
|
|
7
9
|
* @param {string} rawXmlString - Raw XML string
|
|
@@ -439,3 +441,303 @@ export function buildTag(key, value) {
|
|
|
439
441
|
return `<${sanitizedKey}>${value}</${sanitizedKey}>`;
|
|
440
442
|
}
|
|
441
443
|
}
|
|
444
|
+
|
|
445
|
+
// ============================================================================
|
|
446
|
+
// SMART CODE OPTIMIZATION FUNCTIONS
|
|
447
|
+
// ============================================================================
|
|
448
|
+
|
|
449
|
+
/**
|
|
450
|
+
* Detects if a string is likely code.
|
|
451
|
+
* Uses heuristics including command patterns, keywords, and structure.
|
|
452
|
+
* @param {string} value - String to check
|
|
453
|
+
* @returns {boolean} True if the string appears to be code
|
|
454
|
+
*/
|
|
455
|
+
export function isCode(value) {
|
|
456
|
+
if (typeof value !== 'string' || value.length < 5) return false;
|
|
457
|
+
|
|
458
|
+
const trimmed = value.trim();
|
|
459
|
+
|
|
460
|
+
// Single-line command patterns
|
|
461
|
+
const isSingleLineCommand = (
|
|
462
|
+
/^(npm|yarn|pnpm|pip|pip3|brew|apt|gem|go|cargo|composer|mvn|gradle|dotnet|conda)\s+/.test(trimmed) ||
|
|
463
|
+
/^(git|docker|kubectl|curl|wget|ssh|scp|rsync|sudo)\s+/.test(trimmed) ||
|
|
464
|
+
/^(node|python|python3|ruby|java|go|rust)\s+/.test(trimmed) ||
|
|
465
|
+
trimmed.startsWith('$') ||
|
|
466
|
+
trimmed.startsWith('>') ||
|
|
467
|
+
trimmed.startsWith('#!')
|
|
468
|
+
);
|
|
469
|
+
|
|
470
|
+
if (isSingleLineCommand) return true;
|
|
471
|
+
|
|
472
|
+
// Multi-line code detection
|
|
473
|
+
const hasMultipleLines = /\n/.test(trimmed);
|
|
474
|
+
const hasCodePatterns = /import|require\(|function |const |let |var |class |def |async |=>|\[|\];|print\(|console\.log\(/.test(trimmed);
|
|
475
|
+
const startsWithShebang = trimmed.startsWith('#!');
|
|
476
|
+
|
|
477
|
+
return hasMultipleLines && (hasCodePatterns || startsWithShebang);
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* Extracts code blocks from text, separated by double newlines.
|
|
482
|
+
* @param {string} text - Text containing potential code blocks
|
|
483
|
+
* @returns {Array<{code: string, start: number, end: number}>} Array of code block objects
|
|
484
|
+
*/
|
|
485
|
+
export function extractCodeBlocks(text) {
|
|
486
|
+
if (typeof text !== 'string') return [];
|
|
487
|
+
|
|
488
|
+
const results = [];
|
|
489
|
+
let currentPos = 0;
|
|
490
|
+
|
|
491
|
+
while (true) {
|
|
492
|
+
const nextBreak = text.indexOf('\n\n', currentPos);
|
|
493
|
+
let chunk, chunkEnd, nextStart;
|
|
494
|
+
|
|
495
|
+
if (nextBreak !== -1) {
|
|
496
|
+
chunk = text.substring(currentPos, nextBreak);
|
|
497
|
+
chunkEnd = nextBreak;
|
|
498
|
+
nextStart = nextBreak + 2; // skip \n\n
|
|
499
|
+
} else {
|
|
500
|
+
chunk = text.substring(currentPos);
|
|
501
|
+
chunkEnd = text.length;
|
|
502
|
+
nextStart = text.length;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
const cleanChunk = chunk.trim();
|
|
506
|
+
|
|
507
|
+
if (cleanChunk && isCode(cleanChunk)) {
|
|
508
|
+
results.push({
|
|
509
|
+
code: cleanChunk,
|
|
510
|
+
start: currentPos,
|
|
511
|
+
end: chunkEnd
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
currentPos = nextStart;
|
|
516
|
+
if (currentPos >= text.length) break;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
return results;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
/**
|
|
523
|
+
* Reduces a code block by removing comments and compressing whitespace.
|
|
524
|
+
* @param {string} codeBlock - Code to reduce
|
|
525
|
+
* @returns {string} Reduced code
|
|
526
|
+
*/
|
|
527
|
+
export function reduceCodeBlock(codeBlock) {
|
|
528
|
+
let reduced = codeBlock;
|
|
529
|
+
|
|
530
|
+
// Remove double newlines
|
|
531
|
+
reduced = reduced.replace(/\n\n/g, '\n');
|
|
532
|
+
|
|
533
|
+
// Remove single-line comments (# for Python, shell, etc.)
|
|
534
|
+
reduced = reduced.replace(/#.*/g, '');
|
|
535
|
+
|
|
536
|
+
// Remove single-line comments (// for JS, Java, etc.)
|
|
537
|
+
reduced = reduced.replace(/\/\/.*/g, '');
|
|
538
|
+
|
|
539
|
+
// Remove trailing whitespace from each line
|
|
540
|
+
reduced = reduced.replace(/\s*\n/g, '\n');
|
|
541
|
+
|
|
542
|
+
// Remove any remaining double newlines created by comment removal
|
|
543
|
+
reduced = reduced.replace(/\n\n/g, '\n');
|
|
544
|
+
|
|
545
|
+
return reduced.trim();
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
/**
|
|
549
|
+
* Replaces verbose phrases with token-efficient abbreviations.
|
|
550
|
+
* Case-insensitive replacement using EXPENSIVE_WORDS dictionary.
|
|
551
|
+
* @param {string} text - Text to optimize
|
|
552
|
+
* @returns {string} Optimized text
|
|
553
|
+
*/
|
|
554
|
+
export function alterExpensiveWords(text) {
|
|
555
|
+
if (typeof text !== 'string') return text;
|
|
556
|
+
|
|
557
|
+
const keys = Object.keys(EXPENSIVE_WORDS);
|
|
558
|
+
if (keys.length === 0) return text;
|
|
559
|
+
|
|
560
|
+
// Build regex pattern from all keys
|
|
561
|
+
const pattern = new RegExp(
|
|
562
|
+
'\\b(' + keys.map(k => k.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('|') + ')\\b',
|
|
563
|
+
'gi'
|
|
564
|
+
);
|
|
565
|
+
|
|
566
|
+
return text.replace(pattern, (match) => {
|
|
567
|
+
return EXPENSIVE_WORDS[match.toLowerCase()] || match;
|
|
568
|
+
});
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
/**
|
|
572
|
+
* Higher-order function that wraps converters with Smart Code Optimization.
|
|
573
|
+
*
|
|
574
|
+
* Preprocessing steps:
|
|
575
|
+
* 1. Extract code blocks and replace with placeholders
|
|
576
|
+
* 2. Extract data blocks (JSON/XML/CSV) and replace with placeholders
|
|
577
|
+
* 3. Apply expensive word replacements to remaining text
|
|
578
|
+
* 4. Convert data blocks using the converter function
|
|
579
|
+
* 5. Re-insert converted data blocks
|
|
580
|
+
* 6. Reduce and re-insert code blocks
|
|
581
|
+
*
|
|
582
|
+
* @param {Function} converterFn - The converter function to wrap
|
|
583
|
+
* @param {Function} extractFn - Function to extract data blocks (e.g., extractJsonFromString)
|
|
584
|
+
* @returns {Function} Wrapped converter function
|
|
585
|
+
*/
|
|
586
|
+
export function dataManager(converterFn, extractFn) {
|
|
587
|
+
return function (data, ...args) {
|
|
588
|
+
if (typeof data !== 'string') {
|
|
589
|
+
return converterFn(data, ...args);
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
let processedData = data;
|
|
593
|
+
|
|
594
|
+
// Step 1: Extract code blocks and replace with placeholders
|
|
595
|
+
const codeBlocks = extractCodeBlocks(processedData);
|
|
596
|
+
|
|
597
|
+
// Replace from end to start to preserve indices
|
|
598
|
+
for (let i = codeBlocks.length - 1; i >= 0; i--) {
|
|
599
|
+
const block = codeBlocks[i];
|
|
600
|
+
processedData = processedData.substring(0, block.start) +
|
|
601
|
+
`#code#${i}#code#` +
|
|
602
|
+
processedData.substring(block.end);
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
// Step 2: Extract data blocks and replace with placeholders
|
|
606
|
+
const dataBlocks = [];
|
|
607
|
+
let iterationCount = 0;
|
|
608
|
+
const maxIterations = 100;
|
|
609
|
+
|
|
610
|
+
while (iterationCount < maxIterations) {
|
|
611
|
+
const block = extractFn(processedData);
|
|
612
|
+
if (!block) break;
|
|
613
|
+
|
|
614
|
+
dataBlocks.push(block);
|
|
615
|
+
processedData = processedData.replace(block, `#data#${iterationCount}#data#`);
|
|
616
|
+
iterationCount++;
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
// Step 3: Apply expensive word replacements to remaining text
|
|
620
|
+
processedData = alterExpensiveWords(processedData);
|
|
621
|
+
|
|
622
|
+
// Step 4: Compress double newlines
|
|
623
|
+
processedData = processedData.replace(/\n\n/g, '\n');
|
|
624
|
+
|
|
625
|
+
// Step 5: Convert and re-insert data blocks
|
|
626
|
+
let convertedData = processedData.trim();
|
|
627
|
+
|
|
628
|
+
if (dataBlocks.length > 0) {
|
|
629
|
+
// Special Case: If input was 100% one data block and no code blocks, return raw result
|
|
630
|
+
if (dataBlocks.length === 1 && convertedData === '#data#0#data#' && codeBlocks.length === 0) {
|
|
631
|
+
return converterFn(dataBlocks[0].trim(), ...args);
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
for (let i = dataBlocks.length - 1; i >= 0; i--) {
|
|
635
|
+
const block = dataBlocks[i];
|
|
636
|
+
let convertedBlock = converterFn(block.trim(), ...args);
|
|
637
|
+
|
|
638
|
+
// If the converter returned an object/array, stringify it for insertion
|
|
639
|
+
if (typeof convertedBlock !== 'string') {
|
|
640
|
+
try {
|
|
641
|
+
convertedBlock = JSON.stringify(convertedBlock);
|
|
642
|
+
} catch (e) {
|
|
643
|
+
convertedBlock = String(convertedBlock);
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
convertedData = convertedData.replace(`#data#${i}#data#`, convertedBlock);
|
|
648
|
+
}
|
|
649
|
+
} else {
|
|
650
|
+
// No data blocks found, convert the whole thing
|
|
651
|
+
convertedData = converterFn(convertedData, ...args);
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
// Step 6: Reduce and re-insert code blocks
|
|
655
|
+
for (let i = codeBlocks.length - 1; i >= 0; i--) {
|
|
656
|
+
const reducedCode = reduceCodeBlock(codeBlocks[i].code);
|
|
657
|
+
convertedData = convertedData.replace(`#code#${i}#code#`, reducedCode);
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
return convertedData;
|
|
661
|
+
};
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
/**
|
|
665
|
+
* Asynchronous version of dataManager.
|
|
666
|
+
*
|
|
667
|
+
* @param {Function} converterFn - The ASYNC converter function to wrap
|
|
668
|
+
* @param {Function} extractFn - Function to extract data blocks
|
|
669
|
+
* @returns {Function} Wrapped ASYNC converter function
|
|
670
|
+
*/
|
|
671
|
+
export function dataManagerAsync(converterFn, extractFn) {
|
|
672
|
+
return async function (data, ...args) {
|
|
673
|
+
if (typeof data !== 'string') {
|
|
674
|
+
return await converterFn(data, ...args);
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
let processedData = data;
|
|
678
|
+
|
|
679
|
+
// Step 1: Extract code blocks and replace with placeholders
|
|
680
|
+
const codeBlocks = extractCodeBlocks(processedData);
|
|
681
|
+
for (let i = codeBlocks.length - 1; i >= 0; i--) {
|
|
682
|
+
const block = codeBlocks[i];
|
|
683
|
+
processedData = processedData.substring(0, block.start) +
|
|
684
|
+
`#code#${i}#code#` +
|
|
685
|
+
processedData.substring(block.end);
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
// Step 2: Extract data blocks and replace with placeholders
|
|
689
|
+
const dataBlocks = [];
|
|
690
|
+
let iterationCount = 0;
|
|
691
|
+
const maxIterations = 100;
|
|
692
|
+
|
|
693
|
+
while (iterationCount < maxIterations) {
|
|
694
|
+
const block = extractFn(processedData);
|
|
695
|
+
if (!block) break;
|
|
696
|
+
|
|
697
|
+
dataBlocks.push(block);
|
|
698
|
+
processedData = processedData.replace(block, `#data#${iterationCount}#data#`);
|
|
699
|
+
iterationCount++;
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
// Step 3: Apply expensive word replacements
|
|
703
|
+
processedData = alterExpensiveWords(processedData);
|
|
704
|
+
|
|
705
|
+
// Step 4: Compress double newlines
|
|
706
|
+
processedData = processedData.replace(/\n\n/g, '\n');
|
|
707
|
+
|
|
708
|
+
// Step 5: Convert and re-insert data blocks
|
|
709
|
+
let convertedData = processedData.trim();
|
|
710
|
+
|
|
711
|
+
if (dataBlocks.length > 0) {
|
|
712
|
+
// Special Case: If input was 100% one data block and no code blocks, return raw result
|
|
713
|
+
if (dataBlocks.length === 1 && convertedData === '#data#0#data#' && codeBlocks.length === 0) {
|
|
714
|
+
return await converterFn(dataBlocks[0].trim(), ...args);
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
for (let i = dataBlocks.length - 1; i >= 0; i--) {
|
|
718
|
+
const block = dataBlocks[i];
|
|
719
|
+
let convertedBlock = await converterFn(block.trim(), ...args);
|
|
720
|
+
|
|
721
|
+
if (typeof convertedBlock !== 'string') {
|
|
722
|
+
try {
|
|
723
|
+
convertedBlock = JSON.stringify(convertedBlock);
|
|
724
|
+
} catch (e) {
|
|
725
|
+
convertedBlock = String(convertedBlock);
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
convertedData = convertedData.replace(`#data#${i}#data#`, convertedBlock);
|
|
730
|
+
}
|
|
731
|
+
} else {
|
|
732
|
+
convertedData = await converterFn(convertedData, ...args);
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
// Step 6: Reduce and re-insert code blocks
|
|
736
|
+
for (let i = codeBlocks.length - 1; i >= 0; i--) {
|
|
737
|
+
const reducedCode = reduceCodeBlock(codeBlocks[i].code);
|
|
738
|
+
convertedData = convertedData.replace(`#code#${i}#code#`, reducedCode);
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
return convertedData;
|
|
742
|
+
};
|
|
743
|
+
}
|