@willwade/aac-processors 0.1.20 → 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/dist/browser/core/baseProcessor.js +4 -0
- package/dist/browser/processors/applePanelsProcessor.js +33 -40
- package/dist/browser/processors/astericsGridProcessor.js +31 -26
- package/dist/browser/processors/dotProcessor.js +11 -12
- package/dist/browser/processors/gridset/colorUtils.js +354 -0
- package/dist/browser/processors/gridset/helpers.js +60 -53
- package/dist/browser/processors/gridset/index.js +61 -0
- package/dist/browser/processors/gridset/styleHelpers.js +205 -0
- package/dist/browser/processors/gridset/symbolExtractor.js +331 -0
- package/dist/browser/processors/gridset/symbolSearch.js +248 -0
- package/dist/browser/processors/gridset/symbols.js +39 -72
- package/dist/browser/processors/gridsetProcessor.js +39 -48
- package/dist/browser/processors/obfProcessor.js +39 -53
- package/dist/browser/processors/opmlProcessor.js +11 -12
- package/dist/browser/processors/snap/helpers.js +57 -49
- package/dist/browser/processors/snapProcessor.js +48 -51
- package/dist/browser/processors/touchchatProcessor.js +60 -52
- package/dist/browser/utilities/analytics/history.js +24 -18
- package/dist/browser/utilities/analytics/metrics/comparison.js +16 -16
- package/dist/browser/utilities/analytics/metrics/vocabulary.js +2 -2
- package/dist/browser/utilities/analytics/reference/browser.js +16 -16
- package/dist/browser/utilities/analytics/reference/index.js +44 -35
- package/dist/browser/utils/io.js +78 -21
- package/dist/browser/utils/sqlite.js +8 -10
- package/dist/browser/utils/zip.js +43 -43
- package/dist/browser/validation/baseValidator.js +5 -0
- package/dist/browser/validation/gridsetValidator.js +12 -20
- package/dist/browser/validation/obfValidator.js +6 -5
- package/dist/browser/validation/snapValidator.js +11 -7
- package/dist/browser/validation/touchChatValidator.js +23 -13
- package/dist/cli/index.js +22 -24
- package/dist/core/baseProcessor.d.ts +7 -7
- package/dist/core/baseProcessor.js +4 -0
- package/dist/processors/applePanelsProcessor.js +32 -39
- package/dist/processors/astericsGridProcessor.d.ts +4 -4
- package/dist/processors/astericsGridProcessor.js +30 -25
- package/dist/processors/dotProcessor.js +10 -11
- package/dist/processors/excelProcessor.d.ts +3 -3
- package/dist/processors/excelProcessor.js +14 -20
- package/dist/processors/gridset/helpers.d.ts +12 -14
- package/dist/processors/gridset/helpers.js +60 -79
- package/dist/processors/gridset/imageDebug.d.ts +3 -5
- package/dist/processors/gridset/imageDebug.js +4 -4
- package/dist/processors/gridset/password.d.ts +1 -1
- package/dist/processors/gridset/symbolExtractor.d.ts +5 -3
- package/dist/processors/gridset/symbolExtractor.js +15 -38
- package/dist/processors/gridset/symbolSearch.d.ts +11 -10
- package/dist/processors/gridset/symbolSearch.js +29 -51
- package/dist/processors/gridset/symbols.d.ts +8 -6
- package/dist/processors/gridset/symbols.js +38 -71
- package/dist/processors/gridset/wordlistHelpers.d.ts +4 -6
- package/dist/processors/gridset/wordlistHelpers.js +15 -74
- package/dist/processors/gridsetProcessor.d.ts +2 -2
- package/dist/processors/gridsetProcessor.js +38 -70
- package/dist/processors/obfProcessor.d.ts +2 -2
- package/dist/processors/obfProcessor.js +38 -75
- package/dist/processors/obfsetProcessor.js +2 -3
- package/dist/processors/opmlProcessor.js +10 -11
- package/dist/processors/snap/helpers.d.ts +9 -9
- package/dist/processors/snap/helpers.js +58 -76
- package/dist/processors/snapProcessor.d.ts +2 -2
- package/dist/processors/snapProcessor.js +47 -50
- package/dist/processors/touchchatProcessor.d.ts +2 -2
- package/dist/processors/touchchatProcessor.js +59 -51
- package/dist/types/aac.d.ts +2 -2
- package/dist/utilities/analytics/history.d.ts +8 -8
- package/dist/utilities/analytics/history.js +24 -18
- package/dist/utilities/analytics/index.d.ts +3 -2
- package/dist/utilities/analytics/index.js +9 -10
- package/dist/utilities/analytics/metrics/comparison.d.ts +1 -1
- package/dist/utilities/analytics/metrics/comparison.js +16 -16
- package/dist/utilities/analytics/metrics/vocabulary.d.ts +1 -1
- package/dist/utilities/analytics/metrics/vocabulary.js +2 -2
- package/dist/utilities/analytics/reference/browser.d.ts +9 -9
- package/dist/utilities/analytics/reference/browser.js +16 -16
- package/dist/utilities/analytics/reference/index.d.ts +25 -23
- package/dist/utilities/analytics/reference/index.js +43 -34
- package/dist/utilities/symbolTools.d.ts +8 -6
- package/dist/utilities/symbolTools.js +21 -18
- package/dist/utils/io.d.ts +24 -6
- package/dist/utils/io.js +79 -25
- package/dist/utils/sqlite.d.ts +3 -1
- package/dist/utils/sqlite.js +7 -9
- package/dist/utils/zip.d.ts +7 -3
- package/dist/utils/zip.js +43 -43
- package/dist/validation/applePanelsValidator.d.ts +2 -1
- package/dist/validation/applePanelsValidator.js +10 -11
- package/dist/validation/astericsValidator.d.ts +2 -1
- package/dist/validation/astericsValidator.js +5 -4
- package/dist/validation/baseValidator.d.ts +2 -2
- package/dist/validation/baseValidator.js +5 -0
- package/dist/validation/dotValidator.d.ts +2 -1
- package/dist/validation/dotValidator.js +5 -4
- package/dist/validation/excelValidator.d.ts +2 -1
- package/dist/validation/excelValidator.js +5 -4
- package/dist/validation/gridsetValidator.d.ts +2 -1
- package/dist/validation/gridsetValidator.js +11 -22
- package/dist/validation/index.d.ts +2 -2
- package/dist/validation/index.js +5 -4
- package/dist/validation/obfValidator.d.ts +2 -1
- package/dist/validation/obfValidator.js +5 -4
- package/dist/validation/obfsetValidator.d.ts +2 -1
- package/dist/validation/obfsetValidator.js +5 -4
- package/dist/validation/opmlValidator.d.ts +2 -1
- package/dist/validation/opmlValidator.js +5 -4
- package/dist/validation/snapValidator.d.ts +2 -1
- package/dist/validation/snapValidator.js +10 -6
- package/dist/validation/touchChatValidator.d.ts +4 -6
- package/dist/validation/touchChatValidator.js +22 -12
- package/dist/validation/validationTypes.d.ts +8 -1
- package/package.json +1 -1
- package/dist/core/fileProcessor.d.ts +0 -7
- package/dist/core/fileProcessor.js +0 -57
|
@@ -41,6 +41,8 @@
|
|
|
41
41
|
*/
|
|
42
42
|
import { AACSemanticCategory } from './treeStructure';
|
|
43
43
|
import { detectCasing, isNumericOrEmpty } from './stringCasing';
|
|
44
|
+
import { defaultFileAdapter } from '../utils/io';
|
|
45
|
+
import { getZipAdapter } from '../utils/zip';
|
|
44
46
|
class BaseProcessor {
|
|
45
47
|
constructor(options = {}) {
|
|
46
48
|
// Default configuration: exclude navigation/system buttons
|
|
@@ -48,6 +50,8 @@ class BaseProcessor {
|
|
|
48
50
|
excludeNavigationButtons: true,
|
|
49
51
|
excludeSystemButtons: true,
|
|
50
52
|
preserveAllButtons: false,
|
|
53
|
+
fileAdapter: defaultFileAdapter,
|
|
54
|
+
zipAdapter: getZipAdapter,
|
|
51
55
|
...options,
|
|
52
56
|
};
|
|
53
57
|
}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { BaseProcessor, } from '../core/baseProcessor';
|
|
2
2
|
import { AACTree, AACPage, AACButton, AACSemanticCategory, AACSemanticIntent, } from '../core/treeStructure';
|
|
3
|
-
// Removed unused import: FileProcessor
|
|
4
3
|
import plist from 'plist';
|
|
5
4
|
import { ValidationFailureError, buildValidationResultFromMessage, } from '../validation/validationTypes';
|
|
6
|
-
import { getBasename
|
|
5
|
+
import { getBasename } from '../utils/io';
|
|
7
6
|
function isNormalizedPanel(panel) {
|
|
8
7
|
return typeof panel.id === 'string';
|
|
9
8
|
}
|
|
@@ -86,17 +85,15 @@ class ApplePanelsProcessor extends BaseProcessor {
|
|
|
86
85
|
return texts;
|
|
87
86
|
}
|
|
88
87
|
async loadIntoTree(filePathOrBuffer) {
|
|
89
|
-
|
|
88
|
+
const { readBinaryFromInput, readTextFromInput, pathExists, getFileSize, join } = this.options.fileAdapter;
|
|
90
89
|
const filename = typeof filePathOrBuffer === 'string' ? getBasename(filePathOrBuffer) : 'upload.plist';
|
|
91
90
|
let buffer;
|
|
92
91
|
try {
|
|
93
92
|
if (typeof filePathOrBuffer === 'string') {
|
|
94
|
-
const fs = getFs();
|
|
95
|
-
const path = getPath();
|
|
96
93
|
if (filePathOrBuffer.endsWith('.ascconfig')) {
|
|
97
|
-
const panelDefsPath =
|
|
98
|
-
if (
|
|
99
|
-
buffer =
|
|
94
|
+
const panelDefsPath = join(filePathOrBuffer, 'Contents', 'Resources', 'PanelDefinitions.plist');
|
|
95
|
+
if (await pathExists(panelDefsPath)) {
|
|
96
|
+
buffer = await readBinaryFromInput(panelDefsPath);
|
|
100
97
|
}
|
|
101
98
|
else {
|
|
102
99
|
const validation = buildValidationResultFromMessage({
|
|
@@ -111,13 +108,13 @@ class ApplePanelsProcessor extends BaseProcessor {
|
|
|
111
108
|
}
|
|
112
109
|
}
|
|
113
110
|
else {
|
|
114
|
-
buffer =
|
|
111
|
+
buffer = await readBinaryFromInput(filePathOrBuffer);
|
|
115
112
|
}
|
|
116
113
|
}
|
|
117
114
|
else {
|
|
118
|
-
buffer = readBinaryFromInput(filePathOrBuffer);
|
|
115
|
+
buffer = await readBinaryFromInput(filePathOrBuffer);
|
|
119
116
|
}
|
|
120
|
-
const content = readTextFromInput(buffer);
|
|
117
|
+
const content = await readTextFromInput(buffer);
|
|
121
118
|
const parsedData = plist.parse(content);
|
|
122
119
|
let panelsData = [];
|
|
123
120
|
if (Array.isArray(parsedData.panels)) {
|
|
@@ -246,11 +243,12 @@ class ApplePanelsProcessor extends BaseProcessor {
|
|
|
246
243
|
const validation = buildValidationResultFromMessage({
|
|
247
244
|
filename,
|
|
248
245
|
filesize: typeof filePathOrBuffer === 'string'
|
|
249
|
-
? (() => {
|
|
250
|
-
|
|
251
|
-
|
|
246
|
+
? await (async () => {
|
|
247
|
+
return (await pathExists(filePathOrBuffer))
|
|
248
|
+
? await getFileSize(filePathOrBuffer)
|
|
249
|
+
: 0;
|
|
252
250
|
})()
|
|
253
|
-
: readBinaryFromInput(filePathOrBuffer).byteLength,
|
|
251
|
+
: (await readBinaryFromInput(filePathOrBuffer)).byteLength,
|
|
254
252
|
format: 'applepanels',
|
|
255
253
|
message: err?.message || 'Failed to parse Apple Panels file',
|
|
256
254
|
type: 'parse',
|
|
@@ -260,6 +258,7 @@ class ApplePanelsProcessor extends BaseProcessor {
|
|
|
260
258
|
}
|
|
261
259
|
}
|
|
262
260
|
async processTexts(filePathOrBuffer, translations, outputPath) {
|
|
261
|
+
const { readBinaryFromInput, join } = this.options.fileAdapter;
|
|
263
262
|
// Load the tree, apply translations, and save to new file
|
|
264
263
|
const tree = await this.loadIntoTree(filePathOrBuffer);
|
|
265
264
|
// Apply translations to all text content
|
|
@@ -309,15 +308,14 @@ class ApplePanelsProcessor extends BaseProcessor {
|
|
|
309
308
|
// Save the translated tree to the requested location and return its content
|
|
310
309
|
await this.saveFromTree(tree, outputPath);
|
|
311
310
|
if (outputPath.endsWith('.plist')) {
|
|
312
|
-
return readBinaryFromInput(outputPath);
|
|
311
|
+
return await readBinaryFromInput(outputPath);
|
|
313
312
|
}
|
|
314
|
-
const path = getPath();
|
|
315
313
|
const configPath = outputPath.endsWith('.ascconfig') ? outputPath : `${outputPath}.ascconfig`;
|
|
316
|
-
const panelDefsPath =
|
|
317
|
-
return readBinaryFromInput(panelDefsPath);
|
|
314
|
+
const panelDefsPath = join(configPath, 'Contents', 'Resources', 'PanelDefinitions.plist');
|
|
315
|
+
return await readBinaryFromInput(panelDefsPath);
|
|
318
316
|
}
|
|
319
317
|
async saveFromTree(tree, outputPath) {
|
|
320
|
-
|
|
318
|
+
const { writeTextToPath, pathExists, mkDir, join, dirname } = this.options.fileAdapter;
|
|
321
319
|
// Support two output modes:
|
|
322
320
|
// 1) Single-file .plist (PanelDefinitions.plist content written directly)
|
|
323
321
|
// 2) Apple Panels bundle folder (*.ascconfig) with Contents/Resources structure
|
|
@@ -327,17 +325,15 @@ class ApplePanelsProcessor extends BaseProcessor {
|
|
|
327
325
|
let contentsPath = '';
|
|
328
326
|
let resourcesPath = '';
|
|
329
327
|
if (!isSinglePlist) {
|
|
330
|
-
const fs = getFs();
|
|
331
|
-
const path = getPath();
|
|
332
328
|
configPath = outputPath.endsWith('.ascconfig') ? outputPath : `${outputPath}.ascconfig`;
|
|
333
|
-
contentsPath =
|
|
334
|
-
resourcesPath =
|
|
335
|
-
if (!
|
|
336
|
-
|
|
337
|
-
if (!
|
|
338
|
-
|
|
339
|
-
if (!
|
|
340
|
-
|
|
329
|
+
contentsPath = join(configPath, 'Contents');
|
|
330
|
+
resourcesPath = join(contentsPath, 'Resources');
|
|
331
|
+
if (!(await pathExists(configPath)))
|
|
332
|
+
await mkDir(configPath, { recursive: true });
|
|
333
|
+
if (!(await pathExists(contentsPath)))
|
|
334
|
+
await mkDir(contentsPath, { recursive: true });
|
|
335
|
+
if (!(await pathExists(resourcesPath)))
|
|
336
|
+
await mkDir(resourcesPath, { recursive: true });
|
|
341
337
|
// Create Info.plist (bundle mode only)
|
|
342
338
|
const infoPlist = {
|
|
343
339
|
ASCConfigurationDisplayName: tree.metadata?.name || 'AAC Processors Export',
|
|
@@ -353,10 +349,10 @@ class ApplePanelsProcessor extends BaseProcessor {
|
|
|
353
349
|
`Generated by AAC Processors${tree.metadata?.author ? ` - Author: ${tree.metadata.author}` : ''}`,
|
|
354
350
|
};
|
|
355
351
|
const infoPlistContent = plist.build(infoPlist);
|
|
356
|
-
writeTextToPath(
|
|
352
|
+
await writeTextToPath(join(contentsPath, 'Info.plist'), infoPlistContent);
|
|
357
353
|
// Create AssetIndex.plist (empty)
|
|
358
354
|
const assetIndexContent = plist.build({});
|
|
359
|
-
writeTextToPath(
|
|
355
|
+
await writeTextToPath(join(resourcesPath, 'AssetIndex.plist'), assetIndexContent);
|
|
360
356
|
}
|
|
361
357
|
// Build PanelDefinitions content from tree
|
|
362
358
|
const panelsDict = {};
|
|
@@ -482,17 +478,14 @@ class ApplePanelsProcessor extends BaseProcessor {
|
|
|
482
478
|
const panelDefsContent = plist.build(panelDefinitions);
|
|
483
479
|
if (isSinglePlist) {
|
|
484
480
|
// Write single PanelDefinitions.plist file directly
|
|
485
|
-
const
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
490
|
-
writeTextToPath(outputPath, panelDefsContent);
|
|
481
|
+
const dir = dirname(outputPath);
|
|
482
|
+
if (!(await pathExists(dir)))
|
|
483
|
+
await mkDir(dir, { recursive: true });
|
|
484
|
+
await writeTextToPath(outputPath, panelDefsContent);
|
|
491
485
|
}
|
|
492
486
|
else {
|
|
493
487
|
// Write into bundle structure
|
|
494
|
-
|
|
495
|
-
writeTextToPath(path.join(resourcesPath, 'PanelDefinitions.plist'), panelDefsContent);
|
|
488
|
+
await writeTextToPath(join(resourcesPath, 'PanelDefinitions.plist'), panelDefsContent);
|
|
496
489
|
}
|
|
497
490
|
}
|
|
498
491
|
createApplePanelsAction(button) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { BaseProcessor, } from '../core/baseProcessor';
|
|
2
2
|
import { AACTree, AACPage, AACButton, AACSemanticCategory, AACSemanticIntent, } from '../core/treeStructure';
|
|
3
3
|
import { ValidationFailureError, buildValidationResultFromMessage, } from '../validation/validationTypes';
|
|
4
|
-
import { getBasename,
|
|
4
|
+
import { getBasename, encodeBase64 } from '../utils/io';
|
|
5
5
|
const DEFAULT_COLOR_SCHEME_DEFINITIONS = [
|
|
6
6
|
{
|
|
7
7
|
name: 'CS_MODIFIED_FITZGERALD_KEY_VERY_LIGHT',
|
|
@@ -562,7 +562,7 @@ class AstericsGridProcessor extends BaseProcessor {
|
|
|
562
562
|
});
|
|
563
563
|
}
|
|
564
564
|
// Also extract texts from the raw file for comprehensive coverage
|
|
565
|
-
const rawTexts = this.extractRawTexts(filePathOrBuffer);
|
|
565
|
+
const rawTexts = await this.extractRawTexts(filePathOrBuffer);
|
|
566
566
|
rawTexts.forEach((text) => {
|
|
567
567
|
if (text && !texts.includes(text)) {
|
|
568
568
|
texts.push(text);
|
|
@@ -570,8 +570,9 @@ class AstericsGridProcessor extends BaseProcessor {
|
|
|
570
570
|
});
|
|
571
571
|
return texts;
|
|
572
572
|
}
|
|
573
|
-
extractRawTexts(filePathOrBuffer) {
|
|
574
|
-
|
|
573
|
+
async extractRawTexts(filePathOrBuffer) {
|
|
574
|
+
const { readTextFromInput } = this.options.fileAdapter;
|
|
575
|
+
let content = await readTextFromInput(filePathOrBuffer);
|
|
575
576
|
// Remove BOM if present
|
|
576
577
|
if (content.charCodeAt(0) === 0xfeff) {
|
|
577
578
|
content = content.slice(1);
|
|
@@ -651,12 +652,12 @@ class AstericsGridProcessor extends BaseProcessor {
|
|
|
651
652
|
}
|
|
652
653
|
}
|
|
653
654
|
async loadIntoTree(filePathOrBuffer) {
|
|
654
|
-
|
|
655
|
+
const { readBinaryFromInput, readTextFromInput } = this.options.fileAdapter;
|
|
655
656
|
const tree = new AACTree();
|
|
656
657
|
const filename = typeof filePathOrBuffer === 'string' ? getBasename(filePathOrBuffer) : 'upload.grd';
|
|
657
|
-
const buffer = readBinaryFromInput(filePathOrBuffer);
|
|
658
|
+
const buffer = await readBinaryFromInput(filePathOrBuffer);
|
|
658
659
|
try {
|
|
659
|
-
let content = readTextFromInput(buffer);
|
|
660
|
+
let content = await readTextFromInput(buffer);
|
|
660
661
|
// Remove BOM if present
|
|
661
662
|
if (content.charCodeAt(0) === 0xfeff) {
|
|
662
663
|
content = content.slice(1);
|
|
@@ -1049,8 +1050,8 @@ class AstericsGridProcessor extends BaseProcessor {
|
|
|
1049
1050
|
});
|
|
1050
1051
|
}
|
|
1051
1052
|
async processTexts(filePathOrBuffer, translations, outputPath) {
|
|
1052
|
-
|
|
1053
|
-
let content = readTextFromInput(filePathOrBuffer);
|
|
1053
|
+
const { readTextFromInput, readBinaryFromInput, writeTextToPath } = this.options.fileAdapter;
|
|
1054
|
+
let content = await readTextFromInput(filePathOrBuffer);
|
|
1054
1055
|
// Remove BOM if present
|
|
1055
1056
|
if (content.charCodeAt(0) === 0xfeff) {
|
|
1056
1057
|
content = content.slice(1);
|
|
@@ -1059,8 +1060,8 @@ class AstericsGridProcessor extends BaseProcessor {
|
|
|
1059
1060
|
// Apply translations directly to the JSON structure for comprehensive coverage
|
|
1060
1061
|
this.applyTranslationsToGridFile(grdFile, translations);
|
|
1061
1062
|
// Write the translated file
|
|
1062
|
-
writeTextToPath(outputPath, JSON.stringify(grdFile, null, 2));
|
|
1063
|
-
return readBinaryFromInput(outputPath);
|
|
1063
|
+
await writeTextToPath(outputPath, JSON.stringify(grdFile, null, 2));
|
|
1064
|
+
return await readBinaryFromInput(outputPath);
|
|
1064
1065
|
}
|
|
1065
1066
|
applyTranslationsToGridFile(grdFile, translations) {
|
|
1066
1067
|
grdFile.grids.forEach((grid) => {
|
|
@@ -1172,7 +1173,7 @@ class AstericsGridProcessor extends BaseProcessor {
|
|
|
1172
1173
|
}
|
|
1173
1174
|
}
|
|
1174
1175
|
async saveFromTree(tree, outputPath) {
|
|
1175
|
-
|
|
1176
|
+
const { writeTextToPath } = this.options.fileAdapter;
|
|
1176
1177
|
// Use default Asterics Grid styling instead of taking from first page
|
|
1177
1178
|
// This prevents issues where the first page has unusual colors (like purple)
|
|
1178
1179
|
const defaultPageStyle = {
|
|
@@ -1375,13 +1376,14 @@ class AstericsGridProcessor extends BaseProcessor {
|
|
|
1375
1376
|
},
|
|
1376
1377
|
},
|
|
1377
1378
|
};
|
|
1378
|
-
writeTextToPath(outputPath, JSON.stringify(grdFile, null, 2));
|
|
1379
|
+
await writeTextToPath(outputPath, JSON.stringify(grdFile, null, 2));
|
|
1379
1380
|
}
|
|
1380
1381
|
/**
|
|
1381
1382
|
* Add audio recording to a specific grid element
|
|
1382
1383
|
*/
|
|
1383
|
-
addAudioToElement(filePath, elementId, audioData, metadata) {
|
|
1384
|
-
|
|
1384
|
+
async addAudioToElement(filePath, elementId, audioData, metadata) {
|
|
1385
|
+
const { readTextFromInput, writeTextToPath } = this.options.fileAdapter;
|
|
1386
|
+
let content = await readTextFromInput(filePath);
|
|
1385
1387
|
// Remove BOM if present
|
|
1386
1388
|
if (content.charCodeAt(0) === 0xfeff) {
|
|
1387
1389
|
content = content.slice(1);
|
|
@@ -1424,31 +1426,33 @@ class AstericsGridProcessor extends BaseProcessor {
|
|
|
1424
1426
|
throw new Error(`Element with ID ${elementId} not found`);
|
|
1425
1427
|
}
|
|
1426
1428
|
// Write back to file
|
|
1427
|
-
writeTextToPath(filePath, JSON.stringify(grdFile, null, 2));
|
|
1429
|
+
await writeTextToPath(filePath, JSON.stringify(grdFile, null, 2));
|
|
1428
1430
|
}
|
|
1429
1431
|
/**
|
|
1430
1432
|
* Create a copy of the grid file with audio recordings added
|
|
1431
1433
|
*/
|
|
1432
|
-
createAudioEnhancedGridFile(sourceFilePath, targetFilePath, audioMappings) {
|
|
1434
|
+
async createAudioEnhancedGridFile(sourceFilePath, targetFilePath, audioMappings) {
|
|
1435
|
+
const { writeBinaryToPath, readBinaryFromInput } = this.options.fileAdapter;
|
|
1433
1436
|
// Copy the source file to target
|
|
1434
|
-
|
|
1435
|
-
fs.copyFileSync(sourceFilePath, targetFilePath);
|
|
1437
|
+
await writeBinaryToPath(targetFilePath, await readBinaryFromInput(sourceFilePath));
|
|
1436
1438
|
// Add audio recordings to the copy
|
|
1437
|
-
audioMappings.
|
|
1439
|
+
await Promise.all(Object.entries(audioMappings).map(async (item) => {
|
|
1440
|
+
const [elementId, audioInfo] = item;
|
|
1438
1441
|
try {
|
|
1439
|
-
this.addAudioToElement(targetFilePath, elementId, audioInfo.audioData, audioInfo.metadata);
|
|
1442
|
+
await this.addAudioToElement(targetFilePath, elementId, audioInfo.audioData, audioInfo.metadata);
|
|
1440
1443
|
}
|
|
1441
1444
|
catch (error) {
|
|
1442
1445
|
// Failed to add audio to element - continue with others
|
|
1443
1446
|
console.warn(`Failed to add audio to element ${elementId}:`, error);
|
|
1444
1447
|
}
|
|
1445
|
-
});
|
|
1448
|
+
}));
|
|
1446
1449
|
}
|
|
1447
1450
|
/**
|
|
1448
1451
|
* Extract all element IDs from the grid file for audio mapping
|
|
1449
1452
|
*/
|
|
1450
|
-
getElementIds(filePathOrBuffer) {
|
|
1451
|
-
|
|
1453
|
+
async getElementIds(filePathOrBuffer) {
|
|
1454
|
+
const { readTextFromInput } = this.options.fileAdapter;
|
|
1455
|
+
let content = await readTextFromInput(filePathOrBuffer);
|
|
1452
1456
|
// Remove BOM if present
|
|
1453
1457
|
if (content.charCodeAt(0) === 0xfeff) {
|
|
1454
1458
|
content = content.slice(1);
|
|
@@ -1470,8 +1474,9 @@ class AstericsGridProcessor extends BaseProcessor {
|
|
|
1470
1474
|
/**
|
|
1471
1475
|
* Check if an element has audio recording
|
|
1472
1476
|
*/
|
|
1473
|
-
hasAudioRecording(filePathOrBuffer, elementId) {
|
|
1474
|
-
|
|
1477
|
+
async hasAudioRecording(filePathOrBuffer, elementId) {
|
|
1478
|
+
const { readTextFromInput } = this.options.fileAdapter;
|
|
1479
|
+
let content = await readTextFromInput(filePathOrBuffer);
|
|
1475
1480
|
// Remove BOM if present
|
|
1476
1481
|
if (content.charCodeAt(0) === 0xfeff) {
|
|
1477
1482
|
content = content.slice(1);
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { BaseProcessor, } from '../core/baseProcessor';
|
|
2
2
|
import { AACTree, AACPage, AACButton, AACSemanticIntent } from '../core/treeStructure';
|
|
3
|
-
// Removed unused import: FileProcessor
|
|
4
3
|
import { ValidationFailureError, buildValidationResultFromMessage, } from '../validation/validationTypes';
|
|
5
|
-
import { getBasename,
|
|
4
|
+
import { getBasename, encodeText } from '../utils/io';
|
|
6
5
|
class DotProcessor extends BaseProcessor {
|
|
7
6
|
constructor(options) {
|
|
8
7
|
super(options);
|
|
@@ -49,8 +48,8 @@ class DotProcessor extends BaseProcessor {
|
|
|
49
48
|
return { nodes: Array.from(nodes.values()), edges };
|
|
50
49
|
}
|
|
51
50
|
async extractTexts(filePathOrBuffer) {
|
|
52
|
-
|
|
53
|
-
const content = readTextFromInput(filePathOrBuffer);
|
|
51
|
+
const { readTextFromInput } = this.options.fileAdapter;
|
|
52
|
+
const content = await readTextFromInput(filePathOrBuffer);
|
|
54
53
|
const { nodes, edges } = this.parseDotFile(content);
|
|
55
54
|
const texts = [];
|
|
56
55
|
// Collect node labels
|
|
@@ -66,12 +65,12 @@ class DotProcessor extends BaseProcessor {
|
|
|
66
65
|
return texts;
|
|
67
66
|
}
|
|
68
67
|
async loadIntoTree(filePathOrBuffer) {
|
|
69
|
-
|
|
68
|
+
const { readBinaryFromInput, readTextFromInput } = this.options.fileAdapter;
|
|
70
69
|
const filename = typeof filePathOrBuffer === 'string' ? getBasename(filePathOrBuffer) : 'upload.dot';
|
|
71
|
-
const buffer = readBinaryFromInput(filePathOrBuffer);
|
|
70
|
+
const buffer = await readBinaryFromInput(filePathOrBuffer);
|
|
72
71
|
const filesize = buffer.byteLength;
|
|
73
72
|
try {
|
|
74
|
-
const content = readTextFromInput(buffer);
|
|
73
|
+
const content = await readTextFromInput(buffer);
|
|
75
74
|
if (!content || content.trim().length === 0) {
|
|
76
75
|
const validation = buildValidationResultFromMessage({
|
|
77
76
|
filename,
|
|
@@ -155,8 +154,8 @@ class DotProcessor extends BaseProcessor {
|
|
|
155
154
|
}
|
|
156
155
|
}
|
|
157
156
|
async processTexts(filePathOrBuffer, translations, outputPath) {
|
|
158
|
-
|
|
159
|
-
const content = readTextFromInput(filePathOrBuffer);
|
|
157
|
+
const { readTextFromInput, writeBinaryToPath } = this.options.fileAdapter;
|
|
158
|
+
const content = await readTextFromInput(filePathOrBuffer);
|
|
160
159
|
let translatedContent = content;
|
|
161
160
|
translations.forEach((translation, text) => {
|
|
162
161
|
if (typeof text === 'string' && typeof translation === 'string') {
|
|
@@ -167,11 +166,11 @@ class DotProcessor extends BaseProcessor {
|
|
|
167
166
|
}
|
|
168
167
|
});
|
|
169
168
|
const resultBuffer = encodeText(translatedContent || '');
|
|
170
|
-
writeBinaryToPath(outputPath, resultBuffer);
|
|
169
|
+
await writeBinaryToPath(outputPath, resultBuffer);
|
|
171
170
|
return resultBuffer;
|
|
172
171
|
}
|
|
173
172
|
async saveFromTree(tree, _outputPath) {
|
|
174
|
-
|
|
173
|
+
const { writeTextToPath } = this.options.fileAdapter;
|
|
175
174
|
let dotContent = `digraph "${tree.metadata?.name || 'AACBoard'}" {\n`;
|
|
176
175
|
// Helper to escape DOT string
|
|
177
176
|
const escapeDotString = (str) => {
|
|
@@ -201,7 +200,7 @@ class DotProcessor extends BaseProcessor {
|
|
|
201
200
|
});
|
|
202
201
|
}
|
|
203
202
|
dotContent += '}\n';
|
|
204
|
-
writeTextToPath(_outputPath, dotContent);
|
|
203
|
+
await writeTextToPath(_outputPath, dotContent);
|
|
205
204
|
}
|
|
206
205
|
/**
|
|
207
206
|
* Extract strings with metadata for aac-tools-platform compatibility
|