@willwade/aac-processors 0.0.30 → 0.1.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/README.md +52 -852
- package/dist/browser/core/baseProcessor.js +241 -0
- package/dist/browser/core/stringCasing.js +179 -0
- package/dist/browser/core/treeStructure.js +255 -0
- package/dist/browser/index.browser.js +73 -0
- package/dist/browser/processors/applePanelsProcessor.js +582 -0
- package/dist/browser/processors/astericsGridProcessor.js +1509 -0
- package/dist/browser/processors/dotProcessor.js +221 -0
- package/dist/browser/processors/gridset/commands.js +962 -0
- package/dist/browser/processors/gridset/crypto.js +53 -0
- package/dist/browser/processors/gridset/password.js +43 -0
- package/dist/browser/processors/gridset/pluginTypes.js +277 -0
- package/dist/browser/processors/gridset/resolver.js +137 -0
- package/dist/browser/processors/gridset/symbolAlignment.js +276 -0
- package/dist/browser/processors/gridset/symbols.js +421 -0
- package/dist/browser/processors/gridsetProcessor.js +2002 -0
- package/dist/browser/processors/obfProcessor.js +705 -0
- package/dist/browser/processors/opmlProcessor.js +274 -0
- package/dist/browser/types/aac.js +38 -0
- package/dist/browser/utilities/analytics/utils/idGenerator.js +89 -0
- package/dist/browser/utilities/translation/translationProcessor.js +200 -0
- package/dist/browser/utils/io.js +95 -0
- package/dist/browser/validation/baseValidator.js +156 -0
- package/dist/browser/validation/gridsetValidator.js +355 -0
- package/dist/browser/validation/obfValidator.js +500 -0
- package/dist/browser/validation/validationTypes.js +46 -0
- package/dist/cli/index.js +5 -5
- package/dist/core/analyze.d.ts +2 -2
- package/dist/core/analyze.js +2 -2
- package/dist/core/baseProcessor.d.ts +5 -4
- package/dist/core/baseProcessor.js +22 -27
- package/dist/core/treeStructure.d.ts +5 -5
- package/dist/core/treeStructure.js +1 -4
- package/dist/index.browser.d.ts +37 -0
- package/dist/index.browser.js +99 -0
- package/dist/index.d.ts +1 -48
- package/dist/index.js +1 -136
- package/dist/index.node.d.ts +48 -0
- package/dist/index.node.js +152 -0
- package/dist/processors/applePanelsProcessor.d.ts +5 -4
- package/dist/processors/applePanelsProcessor.js +58 -62
- package/dist/processors/astericsGridProcessor.d.ts +7 -6
- package/dist/processors/astericsGridProcessor.js +31 -42
- package/dist/processors/dotProcessor.d.ts +5 -4
- package/dist/processors/dotProcessor.js +25 -33
- package/dist/processors/excelProcessor.d.ts +4 -3
- package/dist/processors/excelProcessor.js +6 -3
- package/dist/processors/gridset/crypto.d.ts +18 -0
- package/dist/processors/gridset/crypto.js +57 -0
- package/dist/processors/gridset/helpers.d.ts +1 -1
- package/dist/processors/gridset/helpers.js +18 -8
- package/dist/processors/gridset/password.d.ts +20 -3
- package/dist/processors/gridset/password.js +17 -3
- package/dist/processors/gridset/wordlistHelpers.d.ts +3 -3
- package/dist/processors/gridset/wordlistHelpers.js +21 -20
- package/dist/processors/gridsetProcessor.d.ts +7 -12
- package/dist/processors/gridsetProcessor.js +116 -77
- package/dist/processors/obfProcessor.d.ts +9 -7
- package/dist/processors/obfProcessor.js +131 -56
- package/dist/processors/obfsetProcessor.d.ts +5 -4
- package/dist/processors/obfsetProcessor.js +10 -16
- package/dist/processors/opmlProcessor.d.ts +5 -4
- package/dist/processors/opmlProcessor.js +27 -34
- package/dist/processors/snapProcessor.d.ts +8 -7
- package/dist/processors/snapProcessor.js +15 -12
- package/dist/processors/touchchatProcessor.d.ts +8 -7
- package/dist/processors/touchchatProcessor.js +22 -17
- package/dist/types/aac.d.ts +0 -2
- package/dist/types/aac.js +2 -0
- package/dist/utils/io.d.ts +12 -0
- package/dist/utils/io.js +107 -0
- package/dist/validation/gridsetValidator.js +7 -7
- package/dist/validation/snapValidator.js +28 -35
- package/docs/BROWSER_USAGE.md +618 -0
- package/examples/README.md +77 -0
- package/examples/browser-test-server.js +81 -0
- package/examples/browser-test.html +331 -0
- package/examples/vitedemo/QUICKSTART.md +74 -0
- package/examples/vitedemo/README.md +157 -0
- package/examples/vitedemo/index.html +376 -0
- package/examples/vitedemo/package-lock.json +1221 -0
- package/examples/vitedemo/package.json +18 -0
- package/examples/vitedemo/src/main.ts +519 -0
- package/examples/vitedemo/test-files/example.dot +14 -0
- package/examples/vitedemo/test-files/example.grd +1 -0
- package/examples/vitedemo/test-files/example.gridset +0 -0
- package/examples/vitedemo/test-files/example.obz +0 -0
- package/examples/vitedemo/test-files/example.opml +18 -0
- package/examples/vitedemo/test-files/simple.obf +53 -0
- package/examples/vitedemo/tsconfig.json +24 -0
- package/examples/vitedemo/vite.config.ts +34 -0
- package/package.json +20 -4
|
@@ -1,19 +1,36 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var
|
|
3
|
-
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
4
24
|
};
|
|
5
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
26
|
exports.GridsetProcessor = void 0;
|
|
7
27
|
const baseProcessor_1 = require("../core/baseProcessor");
|
|
8
28
|
const treeStructure_1 = require("../core/treeStructure");
|
|
9
|
-
const adm_zip_1 = __importDefault(require("adm-zip"));
|
|
10
|
-
const fs_1 = __importDefault(require("fs"));
|
|
11
29
|
const fast_xml_parser_1 = require("fast-xml-parser");
|
|
12
30
|
const resolver_1 = require("./gridset/resolver");
|
|
13
31
|
const translationProcessor_1 = require("../utilities/translation/translationProcessor");
|
|
14
32
|
const password_1 = require("./gridset/password");
|
|
15
|
-
const crypto_1 =
|
|
16
|
-
const zlib_1 = __importDefault(require("zlib"));
|
|
33
|
+
const crypto_1 = require("./gridset/crypto");
|
|
17
34
|
const gridsetValidator_1 = require("../validation/gridsetValidator");
|
|
18
35
|
// New imports for enhanced Grid 3 support
|
|
19
36
|
const pluginTypes_1 = require("./gridset/pluginTypes");
|
|
@@ -22,33 +39,35 @@ const symbols_1 = require("./gridset/symbols");
|
|
|
22
39
|
const resolver_2 = require("./gridset/resolver");
|
|
23
40
|
const idGenerator_1 = require("../utilities/analytics/utils/idGenerator");
|
|
24
41
|
const symbolAlignment_1 = require("./gridset/symbolAlignment");
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Decrypt and inflate a Grid3 encrypted payload (DesktopContentEncrypter).
|
|
31
|
-
* Uses AES-256-CBC with key/IV derived from the password padded with spaces
|
|
32
|
-
* and then Deflate decompression.
|
|
33
|
-
*/
|
|
34
|
-
decryptGridsetEntry(buffer, password) {
|
|
35
|
-
const pwd = (password || 'Chocolate').padEnd(32, ' ');
|
|
36
|
-
const key = Buffer.from(pwd.slice(0, 32), 'utf8');
|
|
37
|
-
const iv = Buffer.from(pwd.slice(0, 16), 'utf8');
|
|
42
|
+
const io_1 = require("../utils/io");
|
|
43
|
+
let JSZipModule;
|
|
44
|
+
async function getJSZip() {
|
|
45
|
+
if (!JSZipModule) {
|
|
38
46
|
try {
|
|
39
|
-
|
|
40
|
-
const
|
|
47
|
+
// Try ES module import first (browser/Vite)
|
|
48
|
+
const module = await Promise.resolve().then(() => __importStar(require('jszip')));
|
|
49
|
+
JSZipModule = module.default || module;
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
// Fall back to CommonJS require (Node.js)
|
|
41
53
|
try {
|
|
42
|
-
|
|
54
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
55
|
+
const module = require('jszip');
|
|
56
|
+
JSZipModule = module.default || module;
|
|
43
57
|
}
|
|
44
|
-
catch {
|
|
45
|
-
|
|
46
|
-
return decrypted;
|
|
58
|
+
catch (err2) {
|
|
59
|
+
throw new Error('Zip handling requires JSZip in this environment.');
|
|
47
60
|
}
|
|
48
61
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
62
|
+
}
|
|
63
|
+
if (!JSZipModule) {
|
|
64
|
+
throw new Error('Zip handling requires JSZip in this environment.');
|
|
65
|
+
}
|
|
66
|
+
return JSZipModule;
|
|
67
|
+
}
|
|
68
|
+
class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
69
|
+
constructor(options) {
|
|
70
|
+
super(options);
|
|
52
71
|
}
|
|
53
72
|
// Determine password to use when opening encrypted gridset archives (.gridsetx)
|
|
54
73
|
getGridsetPassword(source) {
|
|
@@ -394,8 +413,8 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
394
413
|
}
|
|
395
414
|
return undefined;
|
|
396
415
|
}
|
|
397
|
-
extractTexts(filePathOrBuffer) {
|
|
398
|
-
const tree = this.loadIntoTree(filePathOrBuffer);
|
|
416
|
+
async extractTexts(filePathOrBuffer) {
|
|
417
|
+
const tree = await this.loadIntoTree(filePathOrBuffer);
|
|
399
418
|
const texts = [];
|
|
400
419
|
for (const pageId in tree.pages) {
|
|
401
420
|
const page = tree.pages[pageId];
|
|
@@ -410,11 +429,13 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
410
429
|
}
|
|
411
430
|
return texts;
|
|
412
431
|
}
|
|
413
|
-
loadIntoTree(filePathOrBuffer) {
|
|
432
|
+
async loadIntoTree(filePathOrBuffer) {
|
|
414
433
|
const tree = new treeStructure_1.AACTree();
|
|
415
434
|
let zip;
|
|
416
435
|
try {
|
|
417
|
-
|
|
436
|
+
const JSZip = await getJSZip();
|
|
437
|
+
const zipInput = (0, io_1.readBinaryFromInput)(filePathOrBuffer);
|
|
438
|
+
zip = await JSZip.loadAsync(zipInput);
|
|
418
439
|
}
|
|
419
440
|
catch (error) {
|
|
420
441
|
throw new Error(`Invalid ZIP file format: ${error.message}`);
|
|
@@ -430,18 +451,22 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
430
451
|
isSmartBox: isEncryptedArchive, // SmartBox files are .gridsetx encrypted archives
|
|
431
452
|
passwordProtected: !!password,
|
|
432
453
|
};
|
|
433
|
-
const readEntryBuffer = (entry) => {
|
|
434
|
-
|
|
435
|
-
|
|
454
|
+
const readEntryBuffer = async (entry) => {
|
|
455
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-argument
|
|
456
|
+
const raw = await entry.getData();
|
|
457
|
+
if (!isEncryptedArchive) {
|
|
458
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
436
459
|
return raw;
|
|
437
|
-
|
|
460
|
+
}
|
|
461
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-return
|
|
462
|
+
return (0, crypto_1.decryptGridsetEntry)(raw, encryptedContentPassword);
|
|
438
463
|
};
|
|
439
464
|
// Parse FileMap.xml if present to index dynamic files per grid
|
|
440
465
|
const fileMapIndex = new Map();
|
|
441
466
|
try {
|
|
442
467
|
const fmEntry = entries.find((e) => e.entryName.endsWith('FileMap.xml'));
|
|
443
468
|
if (fmEntry) {
|
|
444
|
-
const fmXml = readEntryBuffer(fmEntry)
|
|
469
|
+
const fmXml = (0, io_1.decodeText)(await readEntryBuffer(fmEntry));
|
|
445
470
|
const fmData = parser.parse(fmXml);
|
|
446
471
|
const entries = fmData?.FileMap?.Entries?.Entry || fmData?.fileMap?.entries?.entry;
|
|
447
472
|
if (entries) {
|
|
@@ -476,7 +501,7 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
476
501
|
const styleEntry = entries.find((entry) => entry.entryName.endsWith('styles.xml') || entry.entryName.endsWith('style.xml'));
|
|
477
502
|
if (styleEntry) {
|
|
478
503
|
try {
|
|
479
|
-
const styleXmlContent = readEntryBuffer(styleEntry)
|
|
504
|
+
const styleXmlContent = (0, io_1.decodeText)(await readEntryBuffer(styleEntry));
|
|
480
505
|
const styleData = parser.parse(styleXmlContent);
|
|
481
506
|
// Parse styles and store them in the map
|
|
482
507
|
// Grid3 uses StyleData.Styles.Style with Key attribute
|
|
@@ -507,18 +532,23 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
507
532
|
}
|
|
508
533
|
}
|
|
509
534
|
// Debug: log all entry names
|
|
510
|
-
|
|
535
|
+
console.log('[Gridset] Total zip entries:', entries.length);
|
|
536
|
+
const gridEntries = entries.filter((e) => e.entryName.startsWith('Grids/') && e.entryName.endsWith('grid.xml'));
|
|
537
|
+
console.log('[Gridset] Grid XML entries found:', gridEntries.length);
|
|
538
|
+
if (gridEntries.length > 0) {
|
|
539
|
+
console.log('[Gridset] First few grid entries:', gridEntries.slice(0, 3).map((e) => e.entryName));
|
|
540
|
+
}
|
|
511
541
|
// First pass: collect all grid names and IDs for navigation resolution
|
|
512
542
|
const gridNameToIdMap = new Map();
|
|
513
543
|
const gridIdToNameMap = new Map();
|
|
514
|
-
|
|
544
|
+
for (const entry of entries) {
|
|
515
545
|
if (entry.entryName.startsWith('Grids/') && entry.entryName.endsWith('grid.xml')) {
|
|
516
546
|
try {
|
|
517
|
-
const xmlContent = readEntryBuffer(entry)
|
|
547
|
+
const xmlContent = (0, io_1.decodeText)(await readEntryBuffer(entry));
|
|
518
548
|
const data = parser.parse(xmlContent);
|
|
519
549
|
const grid = data.Grid || data.grid;
|
|
520
550
|
if (!grid)
|
|
521
|
-
|
|
551
|
+
continue;
|
|
522
552
|
const gridId = this.textOf(grid.GridGuid || grid.gridGuid || grid.id);
|
|
523
553
|
const gridName = this.textOf(grid.Name) || this.textOf(grid.name) || this.textOf(grid['@_Name']);
|
|
524
554
|
const folderMatch = entry.entryName.match(/^Grids\/([^/]+)\//);
|
|
@@ -541,32 +571,36 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
541
571
|
// Skip errors in first pass
|
|
542
572
|
}
|
|
543
573
|
}
|
|
544
|
-
}
|
|
574
|
+
}
|
|
545
575
|
// Second pass: process each grid file in the gridset
|
|
546
|
-
|
|
576
|
+
for (const entry of entries) {
|
|
547
577
|
// Only process files named grid.xml under Grids/ (any subdir)
|
|
548
578
|
if (entry.entryName.startsWith('Grids/') && entry.entryName.endsWith('grid.xml')) {
|
|
549
579
|
let xmlContent;
|
|
550
580
|
try {
|
|
551
|
-
|
|
581
|
+
const buffer = await readEntryBuffer(entry);
|
|
582
|
+
xmlContent = (0, io_1.decodeText)(buffer);
|
|
583
|
+
console.log(`[Gridset] Raw XML content (first 200 chars) for ${entry.entryName}:`, xmlContent.substring(0, 200));
|
|
552
584
|
}
|
|
553
585
|
catch (e) {
|
|
554
586
|
// Skip unreadable files
|
|
555
|
-
|
|
587
|
+
continue;
|
|
556
588
|
}
|
|
557
589
|
let data;
|
|
558
590
|
try {
|
|
559
591
|
data = parser.parse(xmlContent);
|
|
592
|
+
console.log(`[Gridset] Parsed ${entry.entryName}, root keys:`, Object.keys(data));
|
|
560
593
|
}
|
|
561
594
|
catch (error) {
|
|
562
595
|
// Skip malformed XML but log the specific error
|
|
563
596
|
console.warn(`Malformed XML in ${entry.entryName}: ${error.message}`);
|
|
564
|
-
|
|
597
|
+
continue;
|
|
565
598
|
}
|
|
566
599
|
// Grid3 XML: <Grid> root
|
|
567
600
|
const grid = data.Grid || data.grid;
|
|
568
601
|
if (!grid) {
|
|
569
|
-
|
|
602
|
+
console.warn(`[Gridset] No Grid/grid found in ${entry.entryName}`);
|
|
603
|
+
continue;
|
|
570
604
|
}
|
|
571
605
|
// Defensive: GridGuid and Name required
|
|
572
606
|
const gridId = this.textOf(grid.GridGuid || grid.gridGuid || grid.id);
|
|
@@ -578,7 +612,7 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
578
612
|
gridName = match[1];
|
|
579
613
|
}
|
|
580
614
|
if (!gridId || !gridName) {
|
|
581
|
-
|
|
615
|
+
continue;
|
|
582
616
|
}
|
|
583
617
|
const page = new treeStructure_1.AACPage({
|
|
584
618
|
id: String(gridId),
|
|
@@ -1334,7 +1368,7 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
1334
1368
|
}
|
|
1335
1369
|
tree.addPage(page);
|
|
1336
1370
|
}
|
|
1337
|
-
}
|
|
1371
|
+
}
|
|
1338
1372
|
// After all pages are loaded, set parentId for navigation targets
|
|
1339
1373
|
for (const pageId in tree.pages) {
|
|
1340
1374
|
const page = tree.pages[pageId];
|
|
@@ -1351,7 +1385,7 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
1351
1385
|
try {
|
|
1352
1386
|
const settingsEntry = entries.find((e) => e.entryName.endsWith('settings.xml'));
|
|
1353
1387
|
if (settingsEntry) {
|
|
1354
|
-
const settingsXml = readEntryBuffer(settingsEntry)
|
|
1388
|
+
const settingsXml = (0, io_1.decodeText)(await readEntryBuffer(settingsEntry));
|
|
1355
1389
|
const settingsData = parser.parse(settingsXml);
|
|
1356
1390
|
const gsName = settingsData?.GridSetSettings?.Name ||
|
|
1357
1391
|
settingsData?.gridSetSettings?.name ||
|
|
@@ -1445,9 +1479,9 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
1445
1479
|
tree.metadata = metadata;
|
|
1446
1480
|
return tree;
|
|
1447
1481
|
}
|
|
1448
|
-
processTexts(filePathOrBuffer, translations, outputPath) {
|
|
1482
|
+
async processTexts(filePathOrBuffer, translations, outputPath) {
|
|
1449
1483
|
// Load the tree, apply translations, and save to new file
|
|
1450
|
-
const tree = this.loadIntoTree(filePathOrBuffer);
|
|
1484
|
+
const tree = await this.loadIntoTree(filePathOrBuffer);
|
|
1451
1485
|
// Apply translations to all text content
|
|
1452
1486
|
Object.values(tree.pages).forEach((page) => {
|
|
1453
1487
|
// Translate page names
|
|
@@ -1505,8 +1539,8 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
1505
1539
|
});
|
|
1506
1540
|
});
|
|
1507
1541
|
// Save the translated tree and return its content
|
|
1508
|
-
this.saveFromTree(tree, outputPath);
|
|
1509
|
-
return
|
|
1542
|
+
await this.saveFromTree(tree, outputPath);
|
|
1543
|
+
return (0, io_1.readBinaryFromInput)(outputPath);
|
|
1510
1544
|
}
|
|
1511
1545
|
/**
|
|
1512
1546
|
* Extract symbol information from a gridset for LLM-based translation.
|
|
@@ -1517,8 +1551,8 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
1517
1551
|
* @param filePathOrBuffer - Path to gridset file or buffer
|
|
1518
1552
|
* @returns Array of symbol information for LLM processing
|
|
1519
1553
|
*/
|
|
1520
|
-
extractSymbolsForLLM(filePathOrBuffer) {
|
|
1521
|
-
const tree = this.loadIntoTree(filePathOrBuffer);
|
|
1554
|
+
async extractSymbolsForLLM(filePathOrBuffer) {
|
|
1555
|
+
const tree = await this.loadIntoTree(filePathOrBuffer);
|
|
1522
1556
|
// Collect all buttons from all pages
|
|
1523
1557
|
const allButtons = [];
|
|
1524
1558
|
Object.values(tree.pages).forEach((page) => {
|
|
@@ -1547,8 +1581,8 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
1547
1581
|
* @param options - Translation options (e.g., allowPartial for testing)
|
|
1548
1582
|
* @returns Buffer of the translated gridset
|
|
1549
1583
|
*/
|
|
1550
|
-
processLLMTranslations(filePathOrBuffer, llmTranslations, outputPath, options) {
|
|
1551
|
-
const tree = this.loadIntoTree(filePathOrBuffer);
|
|
1584
|
+
async processLLMTranslations(filePathOrBuffer, llmTranslations, outputPath, options) {
|
|
1585
|
+
const tree = await this.loadIntoTree(filePathOrBuffer);
|
|
1552
1586
|
// Validate translations using shared utility
|
|
1553
1587
|
const buttonIds = Object.values(tree.pages).flatMap((page) => page.buttons.map((b) => b.id));
|
|
1554
1588
|
(0, translationProcessor_1.validateTranslationResults)(llmTranslations, buttonIds, options);
|
|
@@ -1585,14 +1619,17 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
1585
1619
|
});
|
|
1586
1620
|
});
|
|
1587
1621
|
// Save and return
|
|
1588
|
-
this.saveFromTree(tree, outputPath);
|
|
1589
|
-
return
|
|
1622
|
+
await this.saveFromTree(tree, outputPath);
|
|
1623
|
+
return (0, io_1.readBinaryFromInput)(outputPath);
|
|
1590
1624
|
}
|
|
1591
|
-
saveFromTree(tree, outputPath) {
|
|
1592
|
-
const
|
|
1625
|
+
async saveFromTree(tree, outputPath) {
|
|
1626
|
+
const JSZip = await getJSZip();
|
|
1627
|
+
const zip = new JSZip();
|
|
1593
1628
|
if (Object.keys(tree.pages).length === 0) {
|
|
1594
1629
|
// Create empty zip for empty tree
|
|
1595
|
-
zip.
|
|
1630
|
+
const zipBuffer = await zip.generateAsync({ type: 'uint8array' });
|
|
1631
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
1632
|
+
require('fs').writeFileSync(outputPath, zipBuffer);
|
|
1596
1633
|
return;
|
|
1597
1634
|
}
|
|
1598
1635
|
// Collect all unique styles from pages and buttons
|
|
@@ -1664,7 +1701,7 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
1664
1701
|
suppressEmptyNode: true,
|
|
1665
1702
|
});
|
|
1666
1703
|
const settingsXmlContent = settingsBuilder.build(settingsData);
|
|
1667
|
-
zip.
|
|
1704
|
+
zip.file('Settings0/settings.xml', settingsXmlContent, { binary: false });
|
|
1668
1705
|
// Create Settings0/Styles/style.xml if there are styles
|
|
1669
1706
|
if (uniqueStyles.size > 0) {
|
|
1670
1707
|
const stylesArray = Array.from(uniqueStyles.values()).map(({ id, style }) => {
|
|
@@ -1697,7 +1734,7 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
1697
1734
|
indentBy: ' ',
|
|
1698
1735
|
});
|
|
1699
1736
|
const styleXmlContent = styleBuilder.build(styleData);
|
|
1700
|
-
zip.
|
|
1737
|
+
zip.file('Settings0/Styles/styles.xml', styleXmlContent, { binary: false });
|
|
1701
1738
|
}
|
|
1702
1739
|
// Collect grid file paths for FileMap.xml
|
|
1703
1740
|
const gridFilePaths = [];
|
|
@@ -1780,8 +1817,8 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
1780
1817
|
}
|
|
1781
1818
|
}
|
|
1782
1819
|
const cellData = {
|
|
1783
|
-
'@_X': position.x, // Grid3 uses
|
|
1784
|
-
'@_Y': position.y + yOffset, // Grid3 uses
|
|
1820
|
+
'@_X': position.x + 1, // Grid3 uses 1-based X coordinates
|
|
1821
|
+
'@_Y': position.y + yOffset + 1, // Grid3 uses 1-based Y coordinates with workspace offset
|
|
1785
1822
|
'@_ColumnSpan': position.columnSpan,
|
|
1786
1823
|
'@_RowSpan': position.rowSpan,
|
|
1787
1824
|
Content: {
|
|
@@ -1836,16 +1873,16 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
1836
1873
|
});
|
|
1837
1874
|
const xmlContent = builder.build(gridData);
|
|
1838
1875
|
// Add to zip in Grids folder with proper Grid3 naming
|
|
1839
|
-
const gridPath = `Grids
|
|
1876
|
+
const gridPath = `Grids/${page.name || page.id}/grid.xml`;
|
|
1840
1877
|
gridFilePaths.push(gridPath);
|
|
1841
|
-
zip.
|
|
1878
|
+
zip.file(gridPath, xmlContent, { binary: false });
|
|
1842
1879
|
});
|
|
1843
1880
|
// Write image files to ZIP
|
|
1844
1881
|
buttonImages.forEach((imgData) => {
|
|
1845
1882
|
if (imgData.imageData && imgData.imageData.length > 0) {
|
|
1846
1883
|
// Create image path in the grid's directory
|
|
1847
|
-
const imagePath = `Grids
|
|
1848
|
-
zip.
|
|
1884
|
+
const imagePath = `Grids/${imgData.pageName}/${imgData.x}-${imgData.y}-0-text-0.${imgData.ext}`;
|
|
1885
|
+
zip.file(imagePath, imgData.imageData);
|
|
1849
1886
|
}
|
|
1850
1887
|
});
|
|
1851
1888
|
// Create FileMap.xml to map all grid files with their dynamic image files
|
|
@@ -1856,13 +1893,13 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
1856
1893
|
Entries: {
|
|
1857
1894
|
Entry: gridFilePaths.map((gridPath) => {
|
|
1858
1895
|
// Find all image files for this grid
|
|
1859
|
-
const gridName = gridPath.match(/Grids
|
|
1896
|
+
const gridName = gridPath.match(/Grids\/([^/]+)\/grid\.xml$/)?.[1] || '';
|
|
1860
1897
|
const imageFiles = [];
|
|
1861
1898
|
// Collect image filenames for buttons on this page
|
|
1862
|
-
// IMPORTANT: FileMap.xml requires full paths like "Grids
|
|
1899
|
+
// IMPORTANT: FileMap.xml requires full paths like "Grids/PageName/1-5-0-text-0.png"
|
|
1863
1900
|
buttonImages.forEach((imgData) => {
|
|
1864
1901
|
if (imgData.pageName === gridName && imgData.imageData.length > 0) {
|
|
1865
|
-
const imagePath = `Grids
|
|
1902
|
+
const imagePath = `Grids/${gridName}/${imgData.x}-${imgData.y}-0-text-0.${imgData.ext}`;
|
|
1866
1903
|
imageFiles.push(imagePath);
|
|
1867
1904
|
}
|
|
1868
1905
|
});
|
|
@@ -1884,9 +1921,11 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
1884
1921
|
indentBy: ' ',
|
|
1885
1922
|
});
|
|
1886
1923
|
const fileMapXmlContent = fileMapBuilder.build(fileMapData);
|
|
1887
|
-
zip.
|
|
1924
|
+
zip.file('FileMap.xml', fileMapXmlContent, { binary: false });
|
|
1888
1925
|
// Write the zip file
|
|
1889
|
-
zip.
|
|
1926
|
+
const zipBuffer = await zip.generateAsync({ type: 'uint8array' });
|
|
1927
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
1928
|
+
require('fs').writeFileSync(outputPath, zipBuffer);
|
|
1890
1929
|
}
|
|
1891
1930
|
// Helper method to calculate column definitions based on page layout
|
|
1892
1931
|
calculateColumnDefinitions(page) {
|
|
@@ -2,6 +2,7 @@ import { BaseProcessor, ProcessorOptions, ExtractStringsResult, TranslatedString
|
|
|
2
2
|
import { AACTree } from '../core/treeStructure';
|
|
3
3
|
import { ValidationResult } from '../validation/validationTypes';
|
|
4
4
|
import { type ButtonForTranslation, type LLMLTranslationResult } from '../utilities/translation/translationProcessor';
|
|
5
|
+
import { ProcessorInput } from '../utils/io';
|
|
5
6
|
declare class ObfProcessor extends BaseProcessor {
|
|
6
7
|
private zipFile?;
|
|
7
8
|
private imageCache;
|
|
@@ -16,12 +17,12 @@ declare class ObfProcessor extends BaseProcessor {
|
|
|
16
17
|
private extractImageAsDataUrl;
|
|
17
18
|
private getMimeTypeFromFilename;
|
|
18
19
|
private processBoard;
|
|
19
|
-
extractTexts(filePathOrBuffer:
|
|
20
|
-
loadIntoTree(filePathOrBuffer:
|
|
20
|
+
extractTexts(filePathOrBuffer: ProcessorInput): Promise<string[]>;
|
|
21
|
+
loadIntoTree(filePathOrBuffer: ProcessorInput): Promise<AACTree>;
|
|
21
22
|
private buildGridMetadata;
|
|
22
23
|
private createObfBoardFromPage;
|
|
23
|
-
processTexts(filePathOrBuffer:
|
|
24
|
-
saveFromTree(tree: AACTree, outputPath: string): void
|
|
24
|
+
processTexts(filePathOrBuffer: ProcessorInput, translations: Map<string, string>, outputPath: string): Promise<Uint8Array>;
|
|
25
|
+
saveFromTree(tree: AACTree, outputPath: string): Promise<void>;
|
|
25
26
|
/**
|
|
26
27
|
* Extract strings with metadata for aac-tools-platform compatibility
|
|
27
28
|
* Uses the generic implementation from BaseProcessor
|
|
@@ -47,7 +48,7 @@ declare class ObfProcessor extends BaseProcessor {
|
|
|
47
48
|
* @param filePathOrBuffer - Path to OBF/OBZ file or buffer
|
|
48
49
|
* @returns Array of symbol information for LLM processing
|
|
49
50
|
*/
|
|
50
|
-
extractSymbolsForLLM(filePathOrBuffer:
|
|
51
|
+
extractSymbolsForLLM(filePathOrBuffer: ProcessorInput): Promise<ButtonForTranslation[]>;
|
|
51
52
|
/**
|
|
52
53
|
* Apply LLM translations with symbol information.
|
|
53
54
|
* The LLM should provide translations with symbol attachments in the correct positions.
|
|
@@ -60,8 +61,9 @@ declare class ObfProcessor extends BaseProcessor {
|
|
|
60
61
|
* @param options - Translation options (e.g., allowPartial for testing)
|
|
61
62
|
* @returns Buffer of the translated OBF/OBZ file
|
|
62
63
|
*/
|
|
63
|
-
processLLMTranslations(filePathOrBuffer:
|
|
64
|
+
processLLMTranslations(filePathOrBuffer: ProcessorInput, llmTranslations: LLMLTranslationResult[], outputPath: string, options?: {
|
|
64
65
|
allowPartial?: boolean;
|
|
65
|
-
}):
|
|
66
|
+
}): Promise<Uint8Array>;
|
|
67
|
+
private getObfValidator;
|
|
66
68
|
}
|
|
67
69
|
export { ObfProcessor };
|