@willwade/aac-processors 0.0.9 → 0.0.10
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 +85 -11
- package/dist/cli/index.js +87 -0
- package/dist/core/analyze.js +1 -0
- package/dist/core/baseProcessor.d.ts +3 -0
- package/dist/core/fileProcessor.js +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -0
- package/dist/optional/symbolTools.js +4 -2
- package/dist/processors/gridset/helpers.d.ts +1 -1
- package/dist/processors/gridset/helpers.js +5 -3
- package/dist/processors/gridset/password.d.ts +11 -0
- package/dist/processors/gridset/password.js +37 -0
- package/dist/processors/gridset/resolver.d.ts +1 -1
- package/dist/processors/gridset/resolver.js +8 -4
- package/dist/processors/gridset/wordlistHelpers.d.ts +2 -2
- package/dist/processors/gridset/wordlistHelpers.js +7 -4
- package/dist/processors/gridsetProcessor.d.ts +15 -1
- package/dist/processors/gridsetProcessor.js +64 -22
- package/dist/processors/index.d.ts +1 -0
- package/dist/processors/index.js +5 -2
- package/dist/processors/obfProcessor.d.ts +7 -0
- package/dist/processors/obfProcessor.js +9 -0
- package/dist/processors/snapProcessor.d.ts +7 -0
- package/dist/processors/snapProcessor.js +9 -0
- package/dist/processors/touchchatProcessor.d.ts +7 -0
- package/dist/processors/touchchatProcessor.js +9 -0
- package/dist/utilities/screenshotConverter.d.ts +69 -0
- package/dist/utilities/screenshotConverter.js +453 -0
- package/dist/validation/baseValidator.d.ts +80 -0
- package/dist/validation/baseValidator.js +160 -0
- package/dist/validation/gridsetValidator.d.ts +36 -0
- package/dist/validation/gridsetValidator.js +288 -0
- package/dist/validation/index.d.ts +13 -0
- package/dist/validation/index.js +69 -0
- package/dist/validation/obfValidator.d.ts +44 -0
- package/dist/validation/obfValidator.js +530 -0
- package/dist/validation/snapValidator.d.ts +33 -0
- package/dist/validation/snapValidator.js +237 -0
- package/dist/validation/touchChatValidator.d.ts +33 -0
- package/dist/validation/touchChatValidator.js +229 -0
- package/dist/validation/validationTypes.d.ts +64 -0
- package/dist/validation/validationTypes.js +15 -0
- package/examples/README.md +7 -0
- package/examples/demo.js +143 -0
- package/examples/obf/aboutme.json +376 -0
- package/examples/obf/array.json +6 -0
- package/examples/obf/hash.json +4 -0
- package/examples/obf/links.obz +0 -0
- package/examples/obf/simple.obf +53 -0
- package/examples/package-lock.json +1326 -0
- package/examples/package.json +10 -0
- package/examples/styling-example.ts +316 -0
- package/examples/translate.js +39 -0
- package/examples/translate_demo.js +254 -0
- package/examples/typescript-demo.ts +251 -0
- package/package.json +3 -1
|
@@ -10,10 +10,42 @@ const adm_zip_1 = __importDefault(require("adm-zip"));
|
|
|
10
10
|
const fs_1 = __importDefault(require("fs"));
|
|
11
11
|
const fast_xml_parser_1 = require("fast-xml-parser");
|
|
12
12
|
const resolver_1 = require("./gridset/resolver");
|
|
13
|
+
const password_1 = require("./gridset/password");
|
|
14
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
15
|
+
const zlib_1 = __importDefault(require("zlib"));
|
|
16
|
+
const gridsetValidator_1 = require("../validation/gridsetValidator");
|
|
13
17
|
class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
14
18
|
constructor(options) {
|
|
15
19
|
super(options);
|
|
16
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* Decrypt and inflate a Grid3 encrypted payload (DesktopContentEncrypter).
|
|
23
|
+
* Uses AES-256-CBC with key/IV derived from the password padded with spaces
|
|
24
|
+
* and then Deflate decompression.
|
|
25
|
+
*/
|
|
26
|
+
decryptGridsetEntry(buffer, password) {
|
|
27
|
+
const pwd = (password || 'Chocolate').padEnd(32, ' ');
|
|
28
|
+
const key = Buffer.from(pwd.slice(0, 32), 'utf8');
|
|
29
|
+
const iv = Buffer.from(pwd.slice(0, 16), 'utf8');
|
|
30
|
+
try {
|
|
31
|
+
const decipher = crypto_1.default.createDecipheriv('aes-256-cbc', key, iv);
|
|
32
|
+
const decrypted = Buffer.concat([decipher.update(buffer), decipher.final()]);
|
|
33
|
+
try {
|
|
34
|
+
return zlib_1.default.inflateSync(decrypted);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
// If data isn't deflated, return raw decrypted bytes
|
|
38
|
+
return decrypted;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return buffer;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
// Determine password to use when opening encrypted gridset archives (.gridsetx)
|
|
46
|
+
getGridsetPassword(source) {
|
|
47
|
+
return (0, password_1.resolveGridsetPassword)(this.options, source);
|
|
48
|
+
}
|
|
17
49
|
// Helper function to ensure color has alpha channel (Grid3 format)
|
|
18
50
|
ensureAlphaChannel(color) {
|
|
19
51
|
if (!color)
|
|
@@ -242,10 +274,7 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
242
274
|
return undefined;
|
|
243
275
|
}
|
|
244
276
|
extractTexts(filePathOrBuffer) {
|
|
245
|
-
const
|
|
246
|
-
? filePathOrBuffer
|
|
247
|
-
: fs_1.default.readFileSync(filePathOrBuffer);
|
|
248
|
-
const tree = this.loadIntoTree(buffer);
|
|
277
|
+
const tree = this.loadIntoTree(filePathOrBuffer);
|
|
249
278
|
const texts = [];
|
|
250
279
|
for (const pageId in tree.pages) {
|
|
251
280
|
const page = tree.pages[pageId];
|
|
@@ -269,13 +298,23 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
269
298
|
catch (error) {
|
|
270
299
|
throw new Error(`Invalid ZIP file format: ${error.message}`);
|
|
271
300
|
}
|
|
301
|
+
const password = this.getGridsetPassword(filePathOrBuffer);
|
|
302
|
+
const entries = (0, password_1.getZipEntriesWithPassword)(zip, password);
|
|
272
303
|
const parser = new fast_xml_parser_1.XMLParser({ ignoreAttributes: false });
|
|
304
|
+
const isEncryptedArchive = typeof filePathOrBuffer === 'string' && filePathOrBuffer.toLowerCase().endsWith('.gridsetx');
|
|
305
|
+
const encryptedContentPassword = this.getGridsetPassword(filePathOrBuffer);
|
|
306
|
+
const readEntryBuffer = (entry) => {
|
|
307
|
+
const raw = entry.getData();
|
|
308
|
+
if (!isEncryptedArchive)
|
|
309
|
+
return raw;
|
|
310
|
+
return this.decryptGridsetEntry(raw, encryptedContentPassword);
|
|
311
|
+
};
|
|
273
312
|
// Parse FileMap.xml if present to index dynamic files per grid
|
|
274
313
|
const fileMapIndex = new Map();
|
|
275
314
|
try {
|
|
276
|
-
const fmEntry =
|
|
315
|
+
const fmEntry = entries.find((e) => e.entryName.endsWith('FileMap.xml'));
|
|
277
316
|
if (fmEntry) {
|
|
278
|
-
const fmXml = fmEntry
|
|
317
|
+
const fmXml = readEntryBuffer(fmEntry).toString('utf8');
|
|
279
318
|
const fmData = parser.parse(fmXml);
|
|
280
319
|
const entries = fmData?.FileMap?.Entries?.Entry || fmData?.fileMap?.entries?.entry;
|
|
281
320
|
if (entries) {
|
|
@@ -307,12 +346,10 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
307
346
|
}
|
|
308
347
|
// First, load styles from Settings0/Styles/styles.xml (Grid3 format)
|
|
309
348
|
const styles = new Map();
|
|
310
|
-
const styleEntry =
|
|
311
|
-
.getEntries()
|
|
312
|
-
.find((entry) => entry.entryName.endsWith('styles.xml') || entry.entryName.endsWith('style.xml'));
|
|
349
|
+
const styleEntry = entries.find((entry) => entry.entryName.endsWith('styles.xml') || entry.entryName.endsWith('style.xml'));
|
|
313
350
|
if (styleEntry) {
|
|
314
351
|
try {
|
|
315
|
-
const styleXmlContent = styleEntry
|
|
352
|
+
const styleXmlContent = readEntryBuffer(styleEntry).toString('utf8');
|
|
316
353
|
const styleData = parser.parse(styleXmlContent);
|
|
317
354
|
// Parse styles and store them in the map
|
|
318
355
|
// Grid3 uses StyleData.Styles.Style with Key attribute
|
|
@@ -343,14 +380,14 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
343
380
|
}
|
|
344
381
|
}
|
|
345
382
|
// Debug: log all entry names
|
|
346
|
-
// console.log('Gridset zip entries:',
|
|
383
|
+
// console.log('Gridset zip entries:', entries.map(e => e.entryName));
|
|
347
384
|
// First pass: collect all grid names and IDs for navigation resolution
|
|
348
385
|
const gridNameToIdMap = new Map();
|
|
349
386
|
const gridIdToNameMap = new Map();
|
|
350
|
-
|
|
387
|
+
entries.forEach((entry) => {
|
|
351
388
|
if (entry.entryName.startsWith('Grids/') && entry.entryName.endsWith('grid.xml')) {
|
|
352
389
|
try {
|
|
353
|
-
const xmlContent = entry
|
|
390
|
+
const xmlContent = readEntryBuffer(entry).toString('utf8');
|
|
354
391
|
const data = parser.parse(xmlContent);
|
|
355
392
|
const grid = data.Grid || data.grid;
|
|
356
393
|
if (!grid)
|
|
@@ -373,12 +410,12 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
373
410
|
}
|
|
374
411
|
});
|
|
375
412
|
// Second pass: process each grid file in the gridset
|
|
376
|
-
|
|
413
|
+
entries.forEach((entry) => {
|
|
377
414
|
// Only process files named grid.xml under Grids/ (any subdir)
|
|
378
415
|
if (entry.entryName.startsWith('Grids/') && entry.entryName.endsWith('grid.xml')) {
|
|
379
416
|
let xmlContent;
|
|
380
417
|
try {
|
|
381
|
-
xmlContent = entry
|
|
418
|
+
xmlContent = readEntryBuffer(entry).toString('utf8');
|
|
382
419
|
}
|
|
383
420
|
catch (e) {
|
|
384
421
|
// Skip unreadable files
|
|
@@ -482,7 +519,7 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
482
519
|
x: cellX + 1,
|
|
483
520
|
y: cellY + 1,
|
|
484
521
|
dynamicFiles,
|
|
485
|
-
}) || undefined;
|
|
522
|
+
}, entries) || undefined;
|
|
486
523
|
if (commands) {
|
|
487
524
|
const commandArr = Array.isArray(commands) ? commands : [commands];
|
|
488
525
|
for (const command of commandArr) {
|
|
@@ -910,9 +947,9 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
910
947
|
}
|
|
911
948
|
// Read settings.xml to get the StartGrid (home page)
|
|
912
949
|
try {
|
|
913
|
-
const settingsEntry =
|
|
950
|
+
const settingsEntry = entries.find((e) => e.entryName.endsWith('settings.xml'));
|
|
914
951
|
if (settingsEntry) {
|
|
915
|
-
const settingsXml = settingsEntry
|
|
952
|
+
const settingsXml = readEntryBuffer(settingsEntry).toString('utf8');
|
|
916
953
|
const settingsData = parser.parse(settingsXml);
|
|
917
954
|
const startGridName = settingsData?.GridSetSettings?.StartGrid ||
|
|
918
955
|
settingsData?.gridSetSettings?.startGrid ||
|
|
@@ -933,10 +970,7 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
933
970
|
}
|
|
934
971
|
processTexts(filePathOrBuffer, translations, outputPath) {
|
|
935
972
|
// Load the tree, apply translations, and save to new file
|
|
936
|
-
const
|
|
937
|
-
? filePathOrBuffer
|
|
938
|
-
: fs_1.default.readFileSync(filePathOrBuffer);
|
|
939
|
-
const tree = this.loadIntoTree(buffer);
|
|
973
|
+
const tree = this.loadIntoTree(filePathOrBuffer);
|
|
940
974
|
// Apply translations to all text content
|
|
941
975
|
Object.values(tree.pages).forEach((page) => {
|
|
942
976
|
// Translate page names
|
|
@@ -1327,5 +1361,13 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
1327
1361
|
generateTranslatedDownload(filePath, translatedStrings, sourceStrings) {
|
|
1328
1362
|
return this.generateTranslatedDownloadGeneric(filePath, translatedStrings, sourceStrings);
|
|
1329
1363
|
}
|
|
1364
|
+
/**
|
|
1365
|
+
* Validate Gridset file format
|
|
1366
|
+
* @param filePath - Path to the file to validate
|
|
1367
|
+
* @returns Promise with validation result
|
|
1368
|
+
*/
|
|
1369
|
+
async validate(filePath) {
|
|
1370
|
+
return gridsetValidator_1.GridsetValidator.validateFile(filePath);
|
|
1371
|
+
}
|
|
1330
1372
|
}
|
|
1331
1373
|
exports.GridsetProcessor = GridsetProcessor;
|
|
@@ -11,6 +11,7 @@ export { getPageTokenImageMap, getAllowedImageEntries, openImage, generateGrid3G
|
|
|
11
11
|
export { getPageTokenImageMap as getGridsetPageTokenImageMap, getAllowedImageEntries as getGridsetAllowedImageEntries, openImage as openGridsetImage, generateGrid3Guid as generateGridsetGuid, createSettingsXml as createGridsetSettingsXml, createFileMapXml as createGridsetFileMapXml, getCommonDocumentsPath as getGridsetCommonDocumentsPath, findGrid3UserPaths as findGridsetUserPaths, findGrid3HistoryDatabases as findGridsetHistoryDatabases, findGrid3Users as findGridsetUsers, findGrid3Vocabularies as findGridsetVocabularies, findGrid3UserHistory as findGridsetUserHistory, isGrid3Installed as isGridsetInstalled, readGrid3History as readGridsetHistory, readGrid3HistoryForUser as readGridsetHistoryForUser, readAllGrid3History as readAllGridsetHistory, } from './gridset/helpers';
|
|
12
12
|
export { resolveGrid3CellImage } from './gridset/resolver';
|
|
13
13
|
export { createWordlist, extractWordlists, updateWordlist, wordlistToXml, type WordList, type WordListItem, } from './gridset/wordlistHelpers';
|
|
14
|
+
export { resolveGridsetPassword, resolveGridsetPasswordFromEnv } from './gridset/password';
|
|
14
15
|
export { getNamedColor, rgbaToHex, channelToHex, clampColorChannel, clampAlpha, toHexColor, darkenColor, normalizeColor, ensureAlphaChannel, } from './gridset/colorUtils';
|
|
15
16
|
export { DEFAULT_GRID3_STYLES, CATEGORY_STYLES, createDefaultStylesXml, createCategoryStyle, } from './gridset/styleHelpers';
|
|
16
17
|
export { ensureAlphaChannel as ensureAlphaChannelFromStyles } from './gridset/styleHelpers';
|
package/dist/processors/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
exports.openTouchChatImage = exports.getTouchChatAllowedImageEntries = exports.getTouchChatPageTokenImageMap = exports.readSnapUsageForUser = exports.readSnapUsage = exports.isSnapInstalled = exports.findSnapUserHistory = exports.findSnapUserVocabularies = exports.findSnapUsers = exports.findSnapPackagePath = exports.findSnapPackages = exports.openSnapImage = exports.getSnapAllowedImageEntries = exports.getSnapPageTokenImageMap = exports.ensureAlphaChannelFromStyles = exports.createCategoryStyle = exports.createDefaultStylesXml = exports.CATEGORY_STYLES = exports.DEFAULT_GRID3_STYLES = exports.ensureAlphaChannel = exports.normalizeColor = exports.darkenColor = exports.toHexColor = exports.clampAlpha = void 0;
|
|
3
|
+
exports.rgbaToHex = exports.getNamedColor = exports.resolveGridsetPasswordFromEnv = exports.resolveGridsetPassword = exports.wordlistToXml = exports.updateWordlist = exports.extractWordlists = exports.createWordlist = exports.resolveGrid3CellImage = exports.readAllGridsetHistory = exports.readGridsetHistoryForUser = exports.readGridsetHistory = exports.isGridsetInstalled = exports.findGridsetUserHistory = exports.findGridsetVocabularies = exports.findGridsetUsers = exports.findGridsetHistoryDatabases = exports.findGridsetUserPaths = exports.getGridsetCommonDocumentsPath = exports.createGridsetFileMapXml = exports.createGridsetSettingsXml = exports.generateGridsetGuid = exports.openGridsetImage = exports.getGridsetAllowedImageEntries = exports.getGridsetPageTokenImageMap = exports.readAllGrid3History = exports.readGrid3HistoryForUser = exports.readGrid3History = exports.isGrid3Installed = exports.findGrid3UserHistory = exports.findGrid3Vocabularies = exports.findGrid3Users = exports.findGrid3HistoryDatabases = exports.findGrid3UserPaths = exports.getCommonDocumentsPath = exports.createFileMapXml = exports.createSettingsXml = exports.generateGrid3Guid = exports.openImage = exports.getAllowedImageEntries = exports.getPageTokenImageMap = exports.AstericsGridProcessor = exports.TouchChatProcessor = exports.SnapProcessor = exports.OpmlProcessor = exports.ObfProcessor = exports.GridsetProcessor = exports.ExcelProcessor = exports.DotProcessor = exports.ApplePanelsProcessor = void 0;
|
|
4
|
+
exports.openTouchChatImage = exports.getTouchChatAllowedImageEntries = exports.getTouchChatPageTokenImageMap = exports.readSnapUsageForUser = exports.readSnapUsage = exports.isSnapInstalled = exports.findSnapUserHistory = exports.findSnapUserVocabularies = exports.findSnapUsers = exports.findSnapPackagePath = exports.findSnapPackages = exports.openSnapImage = exports.getSnapAllowedImageEntries = exports.getSnapPageTokenImageMap = exports.ensureAlphaChannelFromStyles = exports.createCategoryStyle = exports.createDefaultStylesXml = exports.CATEGORY_STYLES = exports.DEFAULT_GRID3_STYLES = exports.ensureAlphaChannel = exports.normalizeColor = exports.darkenColor = exports.toHexColor = exports.clampAlpha = exports.clampColorChannel = exports.channelToHex = void 0;
|
|
5
5
|
var applePanelsProcessor_1 = require("./applePanelsProcessor");
|
|
6
6
|
Object.defineProperty(exports, "ApplePanelsProcessor", { enumerable: true, get: function () { return applePanelsProcessor_1.ApplePanelsProcessor; } });
|
|
7
7
|
var dotProcessor_1 = require("./dotProcessor");
|
|
@@ -63,6 +63,9 @@ Object.defineProperty(exports, "createWordlist", { enumerable: true, get: functi
|
|
|
63
63
|
Object.defineProperty(exports, "extractWordlists", { enumerable: true, get: function () { return wordlistHelpers_1.extractWordlists; } });
|
|
64
64
|
Object.defineProperty(exports, "updateWordlist", { enumerable: true, get: function () { return wordlistHelpers_1.updateWordlist; } });
|
|
65
65
|
Object.defineProperty(exports, "wordlistToXml", { enumerable: true, get: function () { return wordlistHelpers_1.wordlistToXml; } });
|
|
66
|
+
var password_1 = require("./gridset/password");
|
|
67
|
+
Object.defineProperty(exports, "resolveGridsetPassword", { enumerable: true, get: function () { return password_1.resolveGridsetPassword; } });
|
|
68
|
+
Object.defineProperty(exports, "resolveGridsetPasswordFromEnv", { enumerable: true, get: function () { return password_1.resolveGridsetPasswordFromEnv; } });
|
|
66
69
|
// Gridset (Grid 3) color utilities
|
|
67
70
|
var colorUtils_1 = require("./gridset/colorUtils");
|
|
68
71
|
Object.defineProperty(exports, "getNamedColor", { enumerable: true, get: function () { return colorUtils_1.getNamedColor; } });
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { BaseProcessor, ProcessorOptions, ExtractStringsResult, TranslatedString, SourceString } from '../core/baseProcessor';
|
|
2
2
|
import { AACTree } from '../core/treeStructure';
|
|
3
|
+
import { ValidationResult } from '../validation/validationTypes';
|
|
3
4
|
declare class ObfProcessor extends BaseProcessor {
|
|
4
5
|
constructor(options?: ProcessorOptions);
|
|
5
6
|
private processBoard;
|
|
@@ -19,5 +20,11 @@ declare class ObfProcessor extends BaseProcessor {
|
|
|
19
20
|
* Uses the generic implementation from BaseProcessor
|
|
20
21
|
*/
|
|
21
22
|
generateTranslatedDownload(filePath: string, translatedStrings: TranslatedString[], sourceStrings: SourceString[]): Promise<string>;
|
|
23
|
+
/**
|
|
24
|
+
* Validate OBF/OBZ file format
|
|
25
|
+
* @param filePath - Path to the file to validate
|
|
26
|
+
* @returns Promise with validation result
|
|
27
|
+
*/
|
|
28
|
+
validate(filePath: string): Promise<ValidationResult>;
|
|
22
29
|
}
|
|
23
30
|
export { ObfProcessor };
|
|
@@ -10,6 +10,7 @@ const treeStructure_1 = require("../core/treeStructure");
|
|
|
10
10
|
const adm_zip_1 = __importDefault(require("adm-zip"));
|
|
11
11
|
const fs_1 = __importDefault(require("fs"));
|
|
12
12
|
// Removed unused import: path
|
|
13
|
+
const obfValidator_1 = require("../validation/obfValidator");
|
|
13
14
|
const OBF_FORMAT_VERSION = 'open-board-0.1';
|
|
14
15
|
class ObfProcessor extends baseProcessor_1.BaseProcessor {
|
|
15
16
|
constructor(options) {
|
|
@@ -359,5 +360,13 @@ class ObfProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
359
360
|
async generateTranslatedDownload(filePath, translatedStrings, sourceStrings) {
|
|
360
361
|
return this.generateTranslatedDownloadGeneric(filePath, translatedStrings, sourceStrings);
|
|
361
362
|
}
|
|
363
|
+
/**
|
|
364
|
+
* Validate OBF/OBZ file format
|
|
365
|
+
* @param filePath - Path to the file to validate
|
|
366
|
+
* @returns Promise with validation result
|
|
367
|
+
*/
|
|
368
|
+
async validate(filePath) {
|
|
369
|
+
return obfValidator_1.ObfValidator.validateFile(filePath);
|
|
370
|
+
}
|
|
362
371
|
}
|
|
363
372
|
exports.ObfProcessor = ObfProcessor;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { BaseProcessor, ProcessorOptions, ExtractStringsResult, TranslatedString, SourceString } from '../core/baseProcessor';
|
|
2
2
|
import { AACTree } from '../core/treeStructure';
|
|
3
|
+
import { ValidationResult } from '../validation/validationTypes';
|
|
3
4
|
declare class SnapProcessor extends BaseProcessor {
|
|
4
5
|
private symbolResolver;
|
|
5
6
|
private loadAudio;
|
|
@@ -40,5 +41,11 @@ declare class SnapProcessor extends BaseProcessor {
|
|
|
40
41
|
* Uses the generic implementation from BaseProcessor
|
|
41
42
|
*/
|
|
42
43
|
generateTranslatedDownload(filePath: string, translatedStrings: TranslatedString[], sourceStrings: SourceString[]): Promise<string>;
|
|
44
|
+
/**
|
|
45
|
+
* Validate Snap file format
|
|
46
|
+
* @param filePath - Path to the file to validate
|
|
47
|
+
* @returns Promise with validation result
|
|
48
|
+
*/
|
|
49
|
+
validate(filePath: string): Promise<ValidationResult>;
|
|
43
50
|
}
|
|
44
51
|
export { SnapProcessor };
|
|
@@ -11,6 +11,7 @@ const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
|
|
|
11
11
|
const path_1 = __importDefault(require("path"));
|
|
12
12
|
const fs_1 = __importDefault(require("fs"));
|
|
13
13
|
const crypto_1 = __importDefault(require("crypto"));
|
|
14
|
+
const snapValidator_1 = require("../validation/snapValidator");
|
|
14
15
|
class SnapProcessor extends baseProcessor_1.BaseProcessor {
|
|
15
16
|
constructor(symbolResolver = null, options = {}) {
|
|
16
17
|
super(options);
|
|
@@ -612,5 +613,13 @@ class SnapProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
612
613
|
async generateTranslatedDownload(filePath, translatedStrings, sourceStrings) {
|
|
613
614
|
return this.generateTranslatedDownloadGeneric(filePath, translatedStrings, sourceStrings);
|
|
614
615
|
}
|
|
616
|
+
/**
|
|
617
|
+
* Validate Snap file format
|
|
618
|
+
* @param filePath - Path to the file to validate
|
|
619
|
+
* @returns Promise with validation result
|
|
620
|
+
*/
|
|
621
|
+
async validate(filePath) {
|
|
622
|
+
return snapValidator_1.SnapValidator.validateFile(filePath);
|
|
623
|
+
}
|
|
615
624
|
}
|
|
616
625
|
exports.SnapProcessor = SnapProcessor;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { BaseProcessor, ProcessorOptions, ExtractStringsResult, TranslatedString, SourceString } from '../core/baseProcessor';
|
|
2
2
|
import { AACTree } from '../core/treeStructure';
|
|
3
|
+
import { ValidationResult } from '../validation/validationTypes';
|
|
3
4
|
declare class TouchChatProcessor extends BaseProcessor {
|
|
4
5
|
private tree;
|
|
5
6
|
private sourceFile;
|
|
@@ -23,5 +24,11 @@ declare class TouchChatProcessor extends BaseProcessor {
|
|
|
23
24
|
* @returns Promise with path to the generated translated file
|
|
24
25
|
*/
|
|
25
26
|
generateTranslatedDownload(filePath: string, translatedStrings: TranslatedString[], sourceStrings: SourceString[]): Promise<string>;
|
|
27
|
+
/**
|
|
28
|
+
* Validate TouchChat file format
|
|
29
|
+
* @param filePath - Path to the file to validate
|
|
30
|
+
* @returns Promise with validation result
|
|
31
|
+
*/
|
|
32
|
+
validate(filePath: string): Promise<ValidationResult>;
|
|
26
33
|
}
|
|
27
34
|
export { TouchChatProcessor };
|
|
@@ -12,6 +12,7 @@ const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
|
|
|
12
12
|
const path_1 = __importDefault(require("path"));
|
|
13
13
|
const fs_1 = __importDefault(require("fs"));
|
|
14
14
|
const os_1 = __importDefault(require("os"));
|
|
15
|
+
const touchChatValidator_1 = require("../validation/touchChatValidator");
|
|
15
16
|
const toNumberOrUndefined = (value) => typeof value === 'number' ? value : undefined;
|
|
16
17
|
const toStringOrUndefined = (value) => typeof value === 'string' && value.length > 0 ? value : undefined;
|
|
17
18
|
const toBooleanOrUndefined = (value) => typeof value === 'number' ? value !== 0 : undefined;
|
|
@@ -787,5 +788,13 @@ class TouchChatProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
787
788
|
return Promise.reject(new Error(`Failed to generate translated download: ${error instanceof Error ? error.message : 'Unknown error'}`));
|
|
788
789
|
}
|
|
789
790
|
}
|
|
791
|
+
/**
|
|
792
|
+
* Validate TouchChat file format
|
|
793
|
+
* @param filePath - Path to the file to validate
|
|
794
|
+
* @returns Promise with validation result
|
|
795
|
+
*/
|
|
796
|
+
async validate(filePath) {
|
|
797
|
+
return touchChatValidator_1.TouchChatValidator.validateFile(filePath);
|
|
798
|
+
}
|
|
790
799
|
}
|
|
791
800
|
exports.TouchChatProcessor = TouchChatProcessor;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { AACPage, AACTree } from '../core/treeStructure';
|
|
2
|
+
export interface ScreenshotCell {
|
|
3
|
+
text: string;
|
|
4
|
+
row: number;
|
|
5
|
+
col: number;
|
|
6
|
+
isCategory?: boolean;
|
|
7
|
+
isNavigation?: boolean;
|
|
8
|
+
isEmpty?: boolean;
|
|
9
|
+
imageUrl?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface ScreenshotGrid {
|
|
12
|
+
rows: number;
|
|
13
|
+
cols: number;
|
|
14
|
+
cells: ScreenshotCell[];
|
|
15
|
+
categories: string[];
|
|
16
|
+
metadata?: {
|
|
17
|
+
timestamp?: string;
|
|
18
|
+
battery?: string;
|
|
19
|
+
date?: string;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export interface ScreenshotPage {
|
|
23
|
+
filename: string;
|
|
24
|
+
grid: ScreenshotGrid;
|
|
25
|
+
extractedAt: Date;
|
|
26
|
+
pageName?: string;
|
|
27
|
+
parentPath?: string;
|
|
28
|
+
pageTitle?: string;
|
|
29
|
+
}
|
|
30
|
+
export interface PageHierarchy {
|
|
31
|
+
[pageId: string]: {
|
|
32
|
+
page: ScreenshotPage;
|
|
33
|
+
children: string[];
|
|
34
|
+
parent?: string;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
export interface ScreenshotConversionOptions {
|
|
38
|
+
includeEmptyCells: boolean;
|
|
39
|
+
generateIds: boolean;
|
|
40
|
+
targetPlatform?: 'grid3' | 'asterics' | 'snap' | 'touchchat';
|
|
41
|
+
language: string;
|
|
42
|
+
fallbackCategory: string;
|
|
43
|
+
filenameDelimiter?: string;
|
|
44
|
+
}
|
|
45
|
+
export declare class ScreenshotConverter {
|
|
46
|
+
private static defaultOptions;
|
|
47
|
+
/**
|
|
48
|
+
* Parse filename to extract page hierarchy and names
|
|
49
|
+
* Examples:
|
|
50
|
+
* - "Home.png" → pageName: "Home", parentPath: ""
|
|
51
|
+
* - "Home->Fragen.png" → pageName: "Fragen", parentPath: "Home"
|
|
52
|
+
* - "Home->Settings->Profile.jpg" → pageName: "Profile", parentPath: "Home->Settings"
|
|
53
|
+
*/
|
|
54
|
+
static parseFilename(filename: string, delimiter?: string): {
|
|
55
|
+
pageName: string;
|
|
56
|
+
parentPath: string;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Build page hierarchy from an array of screenshots
|
|
60
|
+
*/
|
|
61
|
+
static buildPageHierarchy(screenshots: ScreenshotPage[]): PageHierarchy;
|
|
62
|
+
static parseOCRText(ocrResult: string): ScreenshotGrid;
|
|
63
|
+
private static isCategoryToken;
|
|
64
|
+
private static isNavigationToken;
|
|
65
|
+
static convertToAACPage(screenshotPage: ScreenshotPage, pageHierarchy?: PageHierarchy, options?: Partial<ScreenshotConversionOptions>): AACPage;
|
|
66
|
+
private static createSemanticAction;
|
|
67
|
+
static convertToAACTree(screenshotPages: ScreenshotPage[], options?: Partial<ScreenshotConversionOptions>): AACTree;
|
|
68
|
+
private static sanitizePageId;
|
|
69
|
+
}
|