@willwade/aac-processors 0.0.3

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.
Files changed (89) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +787 -0
  3. package/dist/cli/index.d.ts +2 -0
  4. package/dist/cli/index.js +189 -0
  5. package/dist/cli/prettyPrint.d.ts +2 -0
  6. package/dist/cli/prettyPrint.js +28 -0
  7. package/dist/core/analyze.d.ts +6 -0
  8. package/dist/core/analyze.js +49 -0
  9. package/dist/core/baseProcessor.d.ts +94 -0
  10. package/dist/core/baseProcessor.js +208 -0
  11. package/dist/core/fileProcessor.d.ts +7 -0
  12. package/dist/core/fileProcessor.js +51 -0
  13. package/dist/core/stringCasing.d.ts +37 -0
  14. package/dist/core/stringCasing.js +174 -0
  15. package/dist/core/treeStructure.d.ts +190 -0
  16. package/dist/core/treeStructure.js +223 -0
  17. package/dist/index.d.ts +23 -0
  18. package/dist/index.js +96 -0
  19. package/dist/optional/symbolTools.d.ts +28 -0
  20. package/dist/optional/symbolTools.js +126 -0
  21. package/dist/processors/applePanelsProcessor.d.ts +23 -0
  22. package/dist/processors/applePanelsProcessor.js +521 -0
  23. package/dist/processors/astericsGridProcessor.d.ts +49 -0
  24. package/dist/processors/astericsGridProcessor.js +1427 -0
  25. package/dist/processors/dotProcessor.d.ts +21 -0
  26. package/dist/processors/dotProcessor.js +191 -0
  27. package/dist/processors/excelProcessor.d.ts +145 -0
  28. package/dist/processors/excelProcessor.js +556 -0
  29. package/dist/processors/gridset/helpers.d.ts +4 -0
  30. package/dist/processors/gridset/helpers.js +48 -0
  31. package/dist/processors/gridset/resolver.d.ts +8 -0
  32. package/dist/processors/gridset/resolver.js +100 -0
  33. package/dist/processors/gridsetProcessor.d.ts +28 -0
  34. package/dist/processors/gridsetProcessor.js +1339 -0
  35. package/dist/processors/index.d.ts +14 -0
  36. package/dist/processors/index.js +42 -0
  37. package/dist/processors/obfProcessor.d.ts +21 -0
  38. package/dist/processors/obfProcessor.js +278 -0
  39. package/dist/processors/opmlProcessor.d.ts +21 -0
  40. package/dist/processors/opmlProcessor.js +235 -0
  41. package/dist/processors/snap/helpers.d.ts +4 -0
  42. package/dist/processors/snap/helpers.js +27 -0
  43. package/dist/processors/snapProcessor.d.ts +44 -0
  44. package/dist/processors/snapProcessor.js +586 -0
  45. package/dist/processors/touchchat/helpers.d.ts +4 -0
  46. package/dist/processors/touchchat/helpers.js +27 -0
  47. package/dist/processors/touchchatProcessor.d.ts +27 -0
  48. package/dist/processors/touchchatProcessor.js +768 -0
  49. package/dist/types/aac.d.ts +47 -0
  50. package/dist/types/aac.js +2 -0
  51. package/docs/.keep +1 -0
  52. package/docs/ApplePanels.md +309 -0
  53. package/docs/Grid3-XML-Format.md +1788 -0
  54. package/docs/TobiiDynavox-Snap-Details.md +394 -0
  55. package/docs/asterics-Grid-fileformat-details.md +443 -0
  56. package/docs/obf_.obz Open Board File Formats.md +432 -0
  57. package/docs/touchchat.md +520 -0
  58. package/examples/.coverage +0 -0
  59. package/examples/.keep +1 -0
  60. package/examples/README.md +31 -0
  61. package/examples/communikate.dot +2637 -0
  62. package/examples/demo.js +143 -0
  63. package/examples/example-images.gridset +0 -0
  64. package/examples/example.ce +0 -0
  65. package/examples/example.dot +14 -0
  66. package/examples/example.grd +1 -0
  67. package/examples/example.gridset +0 -0
  68. package/examples/example.obf +27 -0
  69. package/examples/example.obz +0 -0
  70. package/examples/example.opml +18 -0
  71. package/examples/example.spb +0 -0
  72. package/examples/example.sps +0 -0
  73. package/examples/example2.grd +1 -0
  74. package/examples/gemini_response.txt +845 -0
  75. package/examples/image-map.js +45 -0
  76. package/examples/package-lock.json +1326 -0
  77. package/examples/package.json +10 -0
  78. package/examples/styled-output/converted-snap-to-touchchat.ce +0 -0
  79. package/examples/styled-output/styled-example.ce +0 -0
  80. package/examples/styled-output/styled-example.gridset +0 -0
  81. package/examples/styled-output/styled-example.obf +37 -0
  82. package/examples/styled-output/styled-example.spb +0 -0
  83. package/examples/styling-example.ts +316 -0
  84. package/examples/translate.js +39 -0
  85. package/examples/translate_demo.js +254 -0
  86. package/examples/translation_cache.json +44894 -0
  87. package/examples/typescript-demo.ts +251 -0
  88. package/examples/unified-interface-demo.ts +183 -0
  89. package/package.json +106 -0
package/README.md ADDED
@@ -0,0 +1,787 @@
1
+ # AACProcessors
2
+
3
+ [![Coverage](https://img.shields.io/badge/coverage-77%25-green.svg)](./coverage)
4
+ [![TypeScript](https://img.shields.io/badge/TypeScript-100%25-blue.svg)](https://www.typescriptlang.org/)
5
+ [![Tests](https://img.shields.io/badge/tests-140%20tests-brightgreen.svg)](./test)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+
8
+ A comprehensive **TypeScript library** for processing AAC (Augmentative and Alternative Communication) file formats with advanced translation support, cross-format conversion, and robust error handling.
9
+
10
+ ## πŸš€ Features
11
+
12
+ ### **Multi-Format Support**
13
+
14
+ - **Snap/SPS** (Tobii Dynavox) - Full database support with audio
15
+ - **Grid3/Gridset** (Smartbox) - XML-based format processing
16
+ - **TouchChat** (PRC-Saltillo) - SQLite database handling
17
+ - **OBF/OBZ** (Open Board Format) - JSON and ZIP support
18
+ - **OPML** (Outline Processor Markup Language) - Hierarchical structures
19
+ - **DOT** (Graphviz) - Graph-based communication boards
20
+ - **Apple Panels** (MacOS) - Plist format support
21
+ - **Asterics Grid** - Native Asterics Grid format with audio
22
+ - **Excel** - Export to Microsoft Excel for vocabulary analysis
23
+
24
+ ### **Advanced Capabilities**
25
+
26
+ - πŸ”„ **Cross-format conversion** - Convert between any supported formats
27
+ - 🌍 **Translation workflows** - Built-in i18n support with `processTexts()`
28
+ - 🎨 **Comprehensive styling support** - Preserve visual appearance across formats
29
+ - πŸ§ͺ **Property-based testing** - Robust validation with 140+ tests
30
+ - ⚑ **Performance optimized** - Memory-efficient processing of large files
31
+ - πŸ›‘οΈ **Error recovery** - Graceful handling of corrupted data
32
+ - πŸ”’ **Thread-safe** - Concurrent processing support
33
+ - πŸ“Š **Comprehensive logging** - Detailed operation insights
34
+
35
+ ---
36
+
37
+ ## πŸ“¦ Installation
38
+
39
+ ### From npm (Recommended)
40
+
41
+ ```bash
42
+ npm install aac-processors
43
+ ```
44
+
45
+ ### From Source
46
+
47
+ ```bash
48
+ git clone https://github.com/willwade/AACProcessors-nodejs.git
49
+ cd AACProcessors-nodejs
50
+ npm install
51
+ npm run build
52
+ ```
53
+
54
+ ### Requirements
55
+
56
+ - **Node.js** 16.0.0 or higher
57
+ - **TypeScript** 5.5+ (for development)
58
+
59
+ ---
60
+
61
+ ## πŸ”§ Quick Start
62
+
63
+ ### Basic Usage (TypeScript/ES6)
64
+
65
+ ```typescript
66
+ import {
67
+ getProcessor,
68
+ DotProcessor,
69
+ SnapProcessor,
70
+ AstericsGridProcessor,
71
+ } from "aac-processors";
72
+
73
+ // Auto-detect processor by file extension
74
+ const processor = getProcessor("communication-board.dot");
75
+ const tree = processor.loadIntoTree("communication-board.dot");
76
+
77
+ // Extract all text content
78
+ const texts = processor.extractTexts("communication-board.dot");
79
+ console.log("Found texts:", texts);
80
+
81
+ // Direct processor usage
82
+ const dotProcessor = new DotProcessor();
83
+ const aacTree = dotProcessor.loadIntoTree("examples/example.dot");
84
+ console.log("Pages:", Object.keys(aacTree.pages).length);
85
+ ```
86
+
87
+ ### Basic Usage (CommonJS)
88
+
89
+ ```javascript
90
+ const { getProcessor, DotProcessor } = require("aac-processors");
91
+
92
+ const processor = getProcessor("board.dot");
93
+ const tree = processor.loadIntoTree("board.dot");
94
+ console.log(tree);
95
+ ```
96
+
97
+ ### Button Filtering System
98
+
99
+ AACProcessors includes an intelligent filtering system to handle navigation bars and system buttons that are common in AAC applications but may not be appropriate when converting between formats.
100
+
101
+ #### **Default Behavior**
102
+
103
+ By default, the following buttons are filtered out during conversion:
104
+
105
+ - **Navigation buttons**: Home, Back (toolbar navigation)
106
+ - **System buttons**: Delete, Clear, Copy (text editing functions)
107
+ - **Label-based filtering**: Buttons with common navigation terms
108
+
109
+ #### **Configuration Options**
110
+
111
+ ```typescript
112
+ import { GridsetProcessor } from "aac-processors";
113
+
114
+ // Default: exclude navigation/system buttons (recommended)
115
+ const processor = new GridsetProcessor();
116
+
117
+ // Preserve all buttons (legacy behavior)
118
+ const processor = new GridsetProcessor({ preserveAllButtons: true });
119
+
120
+ // Custom filtering
121
+ const processor = new GridsetProcessor({
122
+ excludeNavigationButtons: true,
123
+ excludeSystemButtons: false,
124
+ customButtonFilter: (button) => !button.label.includes("Settings"),
125
+ });
126
+ ```
127
+
128
+ #### **Why Filter Buttons?**
129
+
130
+ - **Cleaner conversions**: Navigation bars don't clutter converted vocabularies
131
+ - **Format-appropriate**: Each AAC app handles navigation/system functions in their own UI
132
+ - **Semantic-aware**: Uses proper semantic action detection, not just label matching
133
+
134
+ ### Translation Workflows
135
+
136
+ All processors support built-in translation via the `processTexts()` method:
137
+
138
+ ```typescript
139
+ import { DotProcessor } from "aac-processors";
140
+
141
+ const processor = new DotProcessor();
142
+
143
+ // 1. Extract all translatable text
144
+ const originalTexts = processor.extractTexts("board.dot");
145
+
146
+ // 2. Create translation map (integrate with your translation service)
147
+ const translations = new Map([
148
+ ["Hello", "Hola"],
149
+ ["Goodbye", "AdiΓ³s"],
150
+ ["Food", "Comida"],
151
+ ]);
152
+
153
+ // 3. Apply translations and save
154
+ const translatedBuffer = processor.processTexts(
155
+ "board.dot",
156
+ translations,
157
+ "board-spanish.dot",
158
+ );
159
+
160
+ console.log("Translation complete!");
161
+ ```
162
+
163
+ ### Cross-Format Conversion
164
+
165
+ Convert between any supported AAC formats:
166
+
167
+ ```typescript
168
+ import { DotProcessor, ObfProcessor } from "aac-processors";
169
+
170
+ // Load from DOT format
171
+ const dotProcessor = new DotProcessor();
172
+ const tree = dotProcessor.loadIntoTree("communication-board.dot");
173
+
174
+ // Save as OBF format
175
+ const obfProcessor = new ObfProcessor();
176
+ obfProcessor.saveFromTree(tree, "communication-board.obf");
177
+
178
+ // The tree structure is preserved across formats
179
+ console.log("Conversion complete!");
180
+ ```
181
+
182
+ ### Advanced Usage
183
+
184
+ #### Asterics Grid with Audio Support
185
+
186
+ ```typescript
187
+ import { AstericsGridProcessor } from "aac-processors";
188
+
189
+ // Load Asterics Grid file with audio support
190
+ const processor = new AstericsGridProcessor({ loadAudio: true });
191
+ const tree = processor.loadIntoTree("communication-board.grd");
192
+
193
+ // Access audio recordings from buttons
194
+ tree.traverse((page) => {
195
+ page.buttons.forEach((button) => {
196
+ if (button.audioRecording) {
197
+ console.log(`Button "${button.label}" has audio recording`);
198
+ console.log(
199
+ `Audio data size: ${button.audioRecording.data?.length} bytes`,
200
+ );
201
+ }
202
+ });
203
+ });
204
+
205
+ // Add audio to specific elements
206
+ const audioData = Buffer.from(/* your audio data */);
207
+ processor.addAudioToElement(
208
+ "board.grd",
209
+ "element-id",
210
+ audioData,
211
+ JSON.stringify({ mimeType: "audio/wav", durationMs: 2000 }),
212
+ );
213
+
214
+ // Create enhanced version with multiple audio recordings
215
+ const audioMappings = new Map();
216
+ audioMappings.set("element-1", { audioData: audioBuffer1 });
217
+ audioMappings.set("element-2", { audioData: audioBuffer2 });
218
+ processor.createAudioEnhancedGridFile(
219
+ "source.grd",
220
+ "enhanced.grd",
221
+ audioMappings,
222
+ );
223
+ ```
224
+
225
+ #### Excel Export for Vocabulary Analysis
226
+
227
+ ```typescript
228
+ import { ExcelProcessor, getProcessor } from "aac-processors";
229
+
230
+ // Convert any AAC format to Excel for analysis
231
+ const sourceProcessor = getProcessor("communication-board.gridset");
232
+ const tree = sourceProcessor.loadIntoTree("communication-board.gridset");
233
+
234
+ // Export to Excel with visual styling and navigation
235
+ const excelProcessor = new ExcelProcessor();
236
+ excelProcessor.saveFromTree(tree, "vocabulary-analysis.xlsx");
237
+
238
+ // Each AAC page becomes an Excel worksheet tab
239
+ // Buttons are represented as cells with:
240
+ // - Cell value = button label
241
+ // - Cell background = button background color
242
+ // - Cell font color = button font color
243
+ // - Cell comments = button message/vocalization
244
+ // - Hyperlinks for navigation between worksheets
245
+
246
+ // Optional: Navigation row with standard AAC buttons
247
+ // (Home, Message Bar, Delete, Back, Clear) appears on each worksheet
248
+ ```
249
+
250
+ #### Working with the AACTree Structure
251
+
252
+ ```typescript
253
+ import { AACTree, AACPage, AACButton } from "aac-processors";
254
+
255
+ // Create a communication board programmatically
256
+ const tree = new AACTree();
257
+
258
+ const homePage = new AACPage({
259
+ id: "home",
260
+ name: "Home Page",
261
+ buttons: [],
262
+ });
263
+
264
+ const helloButton = new AACButton({
265
+ id: "btn_hello",
266
+ label: "Hello",
267
+ message: "Hello, how are you?",
268
+ type: "SPEAK",
269
+ });
270
+
271
+ const foodButton = new AACButton({
272
+ id: "btn_food",
273
+ label: "Food",
274
+ message: "I want food",
275
+ type: "NAVIGATE",
276
+ targetPageId: "food_page",
277
+ });
278
+
279
+ homePage.addButton(helloButton);
280
+ homePage.addButton(foodButton);
281
+ tree.addPage(homePage);
282
+
283
+ // Save to any format
284
+ const processor = new DotProcessor();
285
+ processor.saveFromTree(tree, "my-board.dot");
286
+ ```
287
+
288
+ #### Error Handling
289
+
290
+ ```typescript
291
+ import { DotProcessor } from "aac-processors";
292
+
293
+ const processor = new DotProcessor();
294
+
295
+ try {
296
+ const tree = processor.loadIntoTree("potentially-corrupted.dot");
297
+ console.log("Successfully loaded:", Object.keys(tree.pages).length, "pages");
298
+ } catch (error) {
299
+ console.error("Failed to load file:", error.message);
300
+ // Processor handles corruption gracefully and provides meaningful errors
301
+ }
302
+ ```
303
+
304
+ ### Styling Support
305
+
306
+ The library now provides comprehensive styling support across all AAC formats, preserving visual appearance when converting between formats.
307
+
308
+ #### Supported Styling Properties
309
+
310
+ ```typescript
311
+ interface AACStyle {
312
+ backgroundColor?: string; // Button/page background color
313
+ fontColor?: string; // Text color
314
+ borderColor?: string; // Border color
315
+ borderWidth?: number; // Border thickness
316
+ fontSize?: number; // Font size in pixels
317
+ fontFamily?: string; // Font family name
318
+ fontWeight?: string; // "normal" | "bold"
319
+ fontStyle?: string; // "normal" | "italic"
320
+ textUnderline?: boolean; // Text underline
321
+ labelOnTop?: boolean; // Label position (TouchChat)
322
+ transparent?: boolean; // Transparent background
323
+ }
324
+ ```
325
+
326
+ #### Creating Styled AAC Content
327
+
328
+ ```typescript
329
+ import { AACTree, AACPage, AACButton } from "aac-processors";
330
+
331
+ // Create a page with styling
332
+ const page = new AACPage({
333
+ id: "main-page",
334
+ name: "Main Communication Board",
335
+ grid: [],
336
+ buttons: [],
337
+ parentId: null,
338
+ style: {
339
+ backgroundColor: "#f0f8ff",
340
+ fontFamily: "Arial",
341
+ fontSize: 16,
342
+ },
343
+ });
344
+
345
+ // Create buttons with comprehensive styling
346
+ const speakButton = new AACButton({
347
+ id: "speak-btn-1",
348
+ label: "Hello",
349
+ message: "Hello, how are you?",
350
+ type: "SPEAK",
351
+ action: null,
352
+ style: {
353
+ backgroundColor: "#4CAF50",
354
+ fontColor: "#ffffff",
355
+ borderColor: "#45a049",
356
+ borderWidth: 2,
357
+ fontSize: 18,
358
+ fontFamily: "Helvetica",
359
+ fontWeight: "bold",
360
+ labelOnTop: true,
361
+ },
362
+ });
363
+
364
+ const navButton = new AACButton({
365
+ id: "nav-btn-1",
366
+ label: "More",
367
+ message: "Navigate to more options",
368
+ type: "NAVIGATE",
369
+ targetPageId: "more-page",
370
+ action: {
371
+ type: "NAVIGATE",
372
+ targetPageId: "more-page",
373
+ },
374
+ style: {
375
+ backgroundColor: "#2196F3",
376
+ fontColor: "#ffffff",
377
+ borderColor: "#1976D2",
378
+ borderWidth: 1,
379
+ fontSize: 16,
380
+ fontStyle: "italic",
381
+ transparent: false,
382
+ },
383
+ });
384
+
385
+ page.addButton(speakButton);
386
+ page.addButton(navButton);
387
+
388
+ const tree = new AACTree();
389
+ tree.addPage(page);
390
+
391
+ // Save with styling preserved
392
+ import { SnapProcessor } from "aac-processors";
393
+ const processor = new SnapProcessor();
394
+ processor.saveFromTree(tree, "styled-board.spb");
395
+ ```
396
+
397
+ #### Format-Specific Styling Support
398
+
399
+ | Format | Background | Font | Border | Advanced |
400
+ | ----------------- | ---------- | ------------ | ------- | ------------------------------- |
401
+ | **Snap/SPS** | βœ… Full | βœ… Full | βœ… Full | βœ… All properties |
402
+ | **TouchChat** | βœ… Full | βœ… Full | βœ… Full | βœ… Label position, transparency |
403
+ | **OBF/OBZ** | βœ… Yes | ❌ No | βœ… Yes | ❌ Basic only |
404
+ | **Grid3** | βœ… Yes | βœ… Yes | βœ… Yes | βœ… Style references |
405
+ | **Asterics Grid** | βœ… Yes | βœ… Yes | βœ… Yes | βœ… Metadata-based |
406
+ | **Apple Panels** | βœ… Yes | βœ… Size only | ❌ No | βœ… Display weight |
407
+ | **Dot** | ❌No | ❌ Yes | ❌ No | ❌ Basic only |
408
+ | **OPML** | ❌No | ❌ Yes | ❌ No | ❌ Basic only |
409
+ | **Excel** | βœ… Yes | βœ… Size only | ❌ No | βœ… Display weight |
410
+
411
+ #### Cross-Format Styling Conversion
412
+
413
+ ```typescript
414
+ import { getProcessor } from "aac-processors";
415
+
416
+ // Load styled content from TouchChat
417
+ const touchChatProcessor = getProcessor("input.ce");
418
+ const styledTree = touchChatProcessor.loadIntoTree("input.ce");
419
+
420
+ // Convert to Snap format while preserving styling
421
+ const snapProcessor = getProcessor("output.spb");
422
+ snapProcessor.saveFromTree(styledTree, "output.spb");
423
+
424
+ // Styling information is automatically mapped between formats
425
+ console.log("Styling preserved across formats!");
426
+ ```
427
+
428
+ ### CLI Usage
429
+
430
+ The CLI provides three main commands for working with AAC files:
431
+
432
+ #### **Extract Text Content**
433
+
434
+ ```bash
435
+ # Extract all text from an AAC file
436
+ npx aac-processors extract examples/example.dot
437
+
438
+ # With format specification and verbose output
439
+ npx aac-processors extract examples/example.sps --format snap --verbose
440
+ ```
441
+
442
+ #### **Convert Between Formats**
443
+
444
+ ```bash
445
+ # Convert from one format to another (format auto-detected from input extension)
446
+ npx aac-processors convert input.sps output.obf --format obf
447
+
448
+ # Convert TouchChat to Snap format
449
+ npx aac-processors convert communication.ce backup.spb --format snap
450
+
451
+ # Convert any AAC format to Excel for vocabulary analysis
452
+ npx aac-processors convert input.gridset vocabulary-analysis.xlsx --format xlsx
453
+
454
+ # Convert with button filtering options
455
+ npx aac-processors convert input.gridset output.grd --format grd --preserve-all-buttons
456
+ npx aac-processors convert input.ce output.spb --format snap --exclude-buttons "settings,menu"
457
+ npx aac-processors convert input.obf output.gridset --format gridset --no-exclude-system
458
+ ```
459
+
460
+ #### **Analyze File Structure**
461
+
462
+ ```bash
463
+ # Get detailed file information in JSON format
464
+ npx aac-processors analyze examples/example.ce
465
+
466
+ # Get human-readable file information
467
+ npx aac-processors analyze examples/example.gridset --pretty
468
+ ```
469
+
470
+ #### **Available Options**
471
+
472
+ **General Options:**
473
+
474
+ - `--format <format>` - Specify format type (auto-detected if not provided)
475
+ - `--pretty` - Human-readable output (analyze command)
476
+ - `--verbose` - Detailed output (extract command)
477
+ - `--quiet` - Minimal output (extract command)
478
+
479
+ **Button Filtering Options:**
480
+
481
+ - `--preserve-all-buttons` - Preserve all buttons including navigation/system buttons
482
+ - `--no-exclude-navigation` - Don't exclude navigation buttons (Home, Back)
483
+ - `--no-exclude-system` - Don't exclude system buttons (Delete, Clear, etc.)
484
+ - `--exclude-buttons <list>` - Comma-separated list of button labels/terms to exclude
485
+
486
+ **Examples:**
487
+
488
+ ```bash
489
+ # Extract text with all buttons preserved
490
+ npx aac-processors extract input.ce --preserve-all-buttons --verbose
491
+
492
+ # Convert excluding only custom buttons
493
+ npx aac-processors convert input.gridset output.grd --format grd --exclude-buttons "settings,help,menu"
494
+
495
+ # Analyze with navigation buttons excluded but system buttons preserved
496
+ npx aac-processors analyze input.spb --no-exclude-system --pretty
497
+ ```
498
+
499
+ ---
500
+
501
+ ## πŸ“š API Reference
502
+
503
+ ### Core Classes
504
+
505
+ #### `getProcessor(filePathOrExtension: string): BaseProcessor`
506
+
507
+ Factory function that returns the appropriate processor for a file extension.
508
+
509
+ ```typescript
510
+ const processor = getProcessor(".dot"); // Returns DotProcessor
511
+ const processor2 = getProcessor("file.obf"); // Returns ObfProcessor
512
+ ```
513
+
514
+ #### `BaseProcessor`
515
+
516
+ Abstract base class for all processors with these key methods:
517
+
518
+ - `loadIntoTree(filePathOrBuffer: string | Buffer): AACTree` - Load file into tree structure
519
+ - `saveFromTree(tree: AACTree, outputPath: string): void` - Save tree to file
520
+ - `extractTexts(filePathOrBuffer: string | Buffer): string[]` - Extract all text content
521
+ - `processTexts(input: string | Buffer, translations: Map<string, string>, outputPath: string): Buffer` - Apply translations
522
+
523
+ #### `AACTree`
524
+
525
+ Core data structure representing a communication board:
526
+
527
+ ```typescript
528
+ interface AACTree {
529
+ pages: Record<string, AACPage>;
530
+ rootId?: string;
531
+ addPage(page: AACPage): void;
532
+ traverse(callback: (page: AACPage) => void): void;
533
+ }
534
+ ```
535
+
536
+ #### `AACPage`
537
+
538
+ Represents a single page/screen in a communication board:
539
+
540
+ ```typescript
541
+ interface AACPage {
542
+ id: string;
543
+ name: string;
544
+ buttons: AACButton[];
545
+ parentId?: string;
546
+ addButton(button: AACButton): void;
547
+ }
548
+ ```
549
+
550
+ #### `AACButton`
551
+
552
+ Represents a button/cell in a communication board:
553
+
554
+ ```typescript
555
+ interface AACButton {
556
+ id: string;
557
+ label: string;
558
+ message?: string;
559
+ type: "SPEAK" | "NAVIGATE";
560
+ targetPageId?: string; // For navigation buttons
561
+ }
562
+ ```
563
+
564
+ ### Supported Processors
565
+
566
+ | Processor | File Extensions | Description |
567
+ | ----------------------- | --------------- | ----------------------------- |
568
+ | `DotProcessor` | `.dot` | Graphviz DOT format |
569
+ | `OpmlProcessor` | `.opml` | OPML hierarchical format |
570
+ | `ObfProcessor` | `.obf`, `.obz` | Open Board Format (JSON/ZIP) |
571
+ | `SnapProcessor` | `.sps`, `.spb` | Tobii Dynavox Snap format |
572
+ | `GridsetProcessor` | `.gridset` | Smartbox Grid 3 format |
573
+ | `TouchChatProcessor` | `.ce` | PRC-Saltillo TouchChat format |
574
+ | `ApplePanelsProcessor` | `.plist` | iOS Apple Panels format |
575
+ | `AstericsGridProcessor` | `.grd` | Asterics Grid native format |
576
+ | `ExcelProcessor` | `.xlsx` | Microsoft Excel format |
577
+
578
+ ---
579
+
580
+ ## πŸ§ͺ Testing & Quality
581
+
582
+ This library maintains **65% test coverage** with **111 comprehensive tests** including:
583
+
584
+ - **Unit tests** for all processors and core functionality
585
+ - **Integration tests** for cross-format workflows
586
+ - **Property-based tests** using fast-check for edge case discovery
587
+ - **Performance tests** for memory usage and large file handling
588
+ - **Error handling tests** for corrupted data and edge cases
589
+
590
+ ### Running Tests
591
+
592
+ ```bash
593
+ # Run all tests (automatically builds first)
594
+ npm test
595
+
596
+ # Run with coverage report (automatically builds first)
597
+ npm run test:coverage
598
+
599
+ # Run tests in watch mode (automatically builds first)
600
+ npm run test:watch
601
+
602
+ # Generate detailed coverage analysis
603
+ npm run coverage:report
604
+ ```
605
+
606
+ **Note**: All test commands automatically run `npm run build` first to ensure CLI tests have the required `dist/` files. CLI integration tests require the compiled JavaScript files to test the command-line interface.
607
+
608
+ ### Development Commands
609
+
610
+ ```bash
611
+ # Build TypeScript
612
+ npm run build
613
+
614
+ # Watch mode for development
615
+ npm run build:watch
616
+
617
+ # Lint code
618
+ npm run lint
619
+
620
+ # Format code
621
+ npm run format
622
+
623
+ # Type checking
624
+ npm run type-check
625
+ ```
626
+
627
+ ---
628
+
629
+ ## 🀝 Contributing
630
+
631
+ We welcome contributions! Please read our [Contributor License Agreement (CLA)](CLA.md) before you get started.
632
+
633
+ 1. Fork the repository
634
+ 2. Create a feature branch: `git checkout -b feature/amazing-feature`
635
+ 3. Make your changes with tests
636
+ 4. Run the test suite: `npm test`
637
+ 5. Commit your changes: `git commit -m 'Add amazing feature'`
638
+ 6. Push to the branch: `git push origin feature/amazing-feature`
639
+ 7. Open a Pull Request
640
+
641
+ ### Development Setup
642
+
643
+ ```bash
644
+ git clone https://github.com/willwade/AACProcessors-nodejs.git
645
+ cd AACProcessors-nodejs
646
+ npm install
647
+ npm run build
648
+ npm test
649
+ ```
650
+
651
+ ### Environment Variables
652
+
653
+ - Copy the template: `cp .envrc.example .envrc`
654
+ - Fill in your own API keys locally; `.envrc` is ignored to prevent accidental commits
655
+ - If you rotate keys, update only your local `.envrc`β€”never commit real secrets
656
+
657
+ ### Publishing to npm
658
+
659
+ - The repository keeps `package.json` at `0.0.0-development`; release tags control the published version.
660
+ - Create a GitHub release with a semantic tag (e.g. `v2.1.0`). Publishing only runs for non-prerelease tags.
661
+ - Add an `NPM_TOKEN` repository secret with publish rights. The release workflow uses it to authenticate and calls `npm publish`.
662
+ - The workflow (`.github/workflows/publish.yml`) automatically installs dependencies, rewrites the package version from the tag, and runs the standard publish pipeline.
663
+
664
+ **Private distribution options**
665
+ - Unscoped packages on npm must be public. To keep this package private, re-scope it (e.g. `@your-org/aac-processors`) and configure `publishConfig.access: "restricted"`β€”this requires an npm org with paid seats.
666
+ - Alternatively, publish to GitHub Packages by adjusting the workflow’s registry URL and using a `GITHUB_TOKEN` with the `packages: write` permission.
667
+
668
+ ---
669
+
670
+ ## πŸ“„ License
671
+
672
+ MIT License - see [LICENSE](LICENSE) file for details.
673
+
674
+ ---
675
+
676
+ ## πŸ™ Credits
677
+
678
+ Created by **Will Wade** and contributors.
679
+
680
+ Inspired by the Python AACProcessors project
681
+
682
+ ### Related Projects
683
+
684
+ - [AACProcessors (Python)](https://github.com/willwade/AACProcessors) - Original Python implementation
685
+ - [Open Board Format](https://www.openboardformat.org/) - Open standard for communication boards
686
+
687
+ ---
688
+
689
+ ## πŸ“ž Support
690
+
691
+ - πŸ› **Bug Reports**: [GitHub Issues](https://github.com/willwade/AACProcessors-nodejs/issues)
692
+ - πŸ’¬ **Discussions**: [GitHub Discussions](https://github.com/willwade/AACProcessors-nodejs/discussions)
693
+ - πŸ“§ **Email**: wwade@acecentre.org.uk
694
+
695
+ ---
696
+
697
+ ## πŸ“‹ TODO & Roadmap
698
+
699
+ ### πŸ”₯ Critical Priority (Immediate Action Required)
700
+
701
+ - [ ] **Fix audio persistence issues** (5 tests failing) - Resolve functional audio recording persistence in SnapProcessor save/load cycle (reduced from 21 failing tests)
702
+ - [ ] **Resolve database constraint violations** - Fix UNIQUE constraint failures in Page.Id and buttons.id when processing real-world data files (blocks production usage)
703
+ - [ ] **Fix Grid3 layout issues** - Grid sizes not reliable and X,Y positions incorrect, particularly affecting Grid3 processor functionality
704
+
705
+ ### 🚨 High Priority (Next Sprint)
706
+
707
+ - [ ] **Complete SnapProcessor coverage** (currently 48.32% - lowest processor) - Add comprehensive audio handling, database corruption tests, and SQLite schema validation to reach >75% coverage
708
+ - [ ] **Reduce remaining linting issues** (123 remaining) - Address TypeScript eslint errors and warnings in test files and less critical areas
709
+ - [ ] **Improve GridsetProcessor coverage** (currently 71.69%) - Enhance ZIP handling and complex Grid3 archive support to reach >80% coverage
710
+
711
+ ### ⚠️ Medium Priority (Following Sprint)
712
+
713
+ - [ ] **Improve GridsetProcessor coverage** (currently 71.69%) - Enhance ZIP handling and complex Grid3 archive support to reach >80% coverage
714
+ - [ ] **Improve AstericsGridProcessor coverage** (currently 62.5%) - Add comprehensive tests for Asterics Grid format processing to reach >80% coverage
715
+ - [ ] **Add Symbol Tools coverage** (currently 0%) - Implement tests for PCS and ARASAAC symbol lookups to reach >70% coverage
716
+ - [ ] **Fix property-based test failures** - Resolve TypeScript interface compatibility issues in edge case generators
717
+
718
+ ### Recently Completed βœ…
719
+
720
+ - [x] **Core utilities test coverage** - Complete implementation for analyze.ts and fileProcessor.ts (0% β†’ 100% coverage, 45 comprehensive tests, src/core/ directory 30% β†’ 83% coverage)
721
+ - [x] **CLI test infrastructure** - Fixed DotProcessor parsing and test expectations (0 β†’ 25 passing tests, 100% CLI functionality)
722
+ - [x] **Critical linting fixes** - Resolved unsafe argument types and CLI type safety issues (177 β†’ 123 errors, 32% improvement)
723
+ - [x] **Audio test syntax fixes** - Fixed non-null assertion errors in audio tests (21 β†’ 5 failing tests, 76% improvement)
724
+ - [x] **Comprehensive styling support** - Complete implementation across all AAC formats with cross-format preservation (Added: AACStyle interface, enhanced all processors, 7 new test cases, complete documentation)
725
+ - [x] **TouchChatProcessor save/load functionality** - Fixed button persistence and ID mapping (coverage improved from 57.62% to 86.44%)
726
+ - [x] **Build integration** - Ensure `npm run build` is executed before CLI tests (Fixed: All test scripts now automatically build before running)
727
+
728
+ ### Medium Priority
729
+
730
+ - [ ] **Performance optimization** - Optimize memory usage for very large communication boards (1000+ buttons)
731
+ - [ ] **Add GridsetProcessor ZIP handling** - Improve support for complex Grid3 ZIP archives
732
+ - [ ] **Enhance error recovery** - Better handling of partially corrupted database files
733
+ - [ ] **Add streaming support** - Process very large files without loading entirely into memory
734
+ - [ ] **Improve translation workflows** - Add support for translation service integrations (Google Translate, Azure, etc.)
735
+ - [ ] **Add symbol library integration** - Complete implementation of PCS, ARASAAC symbol lookups
736
+
737
+ ### Low Priority
738
+
739
+ - [ ] **Add more AAC formats** - Look for other common AAC formats to add
740
+ - [ ] **Plugin system** - Allow third-party processors and extensions
741
+ - [ ] **Batch processing CLI** - Process multiple files in parallel
742
+ - [ ] **Configuration file support** - Allow .aacprocessors.json config files
743
+
744
+ ### Testing & Quality
745
+
746
+ - [ ] **Reach 80%+ test coverage** - Current: 65.15% (target: 80%+)
747
+ - [ ] **Add mutation testing** - Use Stryker.js for mutation testing
748
+ - [ ] **Add benchmark suite** - Performance regression testing
749
+ - [ ] **CI/CD improvements** - Add automated releases and npm publishing
750
+ - [ ] **Documentation improvements** - Add more real-world examples and tutorials
751
+
752
+ ### Known Issues
753
+
754
+ - ⚠️ **Audio Persistence**: 5 functional tests failing due to audio recording not persisting through SnapProcessor save/load cycle
755
+ - ⚠️ **Grid3 Layout**: Grid sizes not reliable and X,Y positions incorrect, particularly affecting Grid3 processor functionality
756
+ - ⚠️ **Database Constraints**: UNIQUE constraint violations with real-world data files (Page.Id and buttons.id conflicts)
757
+ - ⚠️ **Linting**: 123 ESLint issues remaining (mostly in test files, reduced from 177)
758
+ - ⚠️ **SnapProcessor**: Lowest coverage at 48.32%, missing comprehensive audio handling tests
759
+ - ⚠️ **Memory usage**: Large files (>50MB) may cause memory pressure
760
+ - ⚠️ **Concurrent access**: Some processors not fully thread-safe for simultaneous writes
761
+
762
+ ### πŸ§ͺ Current Test Status & Immediate Follow-Up
763
+
764
+ As of the latest run (`npm test`), **47 suites pass / 6 fail (10 individual tests)**. Remaining blockers are:
765
+
766
+ 1. **Edge-case loaders** – corrupted JSON/XML fixtures still expect explicit exceptions. Decide whether to restore the old throwing behaviour (Asterics/OPML/DOT) or update the tests to accept the softer error reporting.
767
+ 2. **Gridset exports & styling** – round-trip continues to lose a button and the styling suite cannot find `style.xml`. GridsetProcessor needs to preserve button arrays and emit the styling assets Grid 3 expects.
768
+ 3. **DOT navigation semantics** – the deterministic DOT test still falls back to `SPEAK`. Improve semantic reconstruction when loading navigation edges so navigation buttons survive round-trips.
769
+ 4. **Advanced workflow scenario** – the multi-format pipeline still loses Spanish translations (likely during the Gridset ⇄ Snap steps); trace text propagation and patch the conversion chain.
770
+ 5. **Styling suite** – Grid 3 export still lacks `style.xml`; ensure the styling assets are generated alongside the gridset payload.
771
+ 6. **Memory comparison suite** – memory delta expectations are still unmet (TouchChat GC + DOT vs others). Either recalibrate the harness or tune the processors before re-enabling the assertions.
772
+
773
+ Clearing these items will put the test matrix back in the green and unblock the release.
774
+
775
+ ## More enhancements
776
+
777
+ - Much more effort put into fixing the layout issues. Grid sizes are not reliably and X, Y positions too. Particularly in the Grid3
778
+ - Action types on buttons. We have SPEAK, NAVIGATE, but we could also have things like "PLAY_AUDIO", "SEND_MESSAGE", "OPEN_URL", etc. This would allow us to have a more flexible structure for actions, especially if we want to support different types of actions or additional metadata in the future. This needs to be very flexible. eaach system has a very different set of actions. We could have a set of core actions that are supported by all systems, and then allow each system to define its own additional actions. This could be done by having a set of core action types that are defined in the AACSystem type, and then allowing each system to define its own additional action types in the AACPageSet or AACPage types.
779
+ - Current language and locale information of aac pageset
780
+ - Symbols and their associated data. Now we have an optional part but I think this might need rethinking. I wonder if "Symbols" should be a separate type - alongside AACPageSet and AACPage. that then AACPageSet and AACPage can reference. This would allow us to have a more flexible structure for symbols, especially if we want to support different types of symbols or additional metadata in the future. Symbols would have: Library name, ID, Text name, Reference (URL, DB ID, etc.), and an optional part for additional metadata. We could have synoynms, antonyms, also and for different languages somehow.
781
+ - Somehow we need to deal with access. Switch scanning: Blocks probably being the main aspect. But also - we need to identify somewhere a set of core rules for each aac system. Like for example - what access methods are supported, what languages are supported, what symbols are supported, etc. This could be a set of rules that can be referenced by AACSystem - a different type altogether maybe? It could be in a JSON format maybe. (use case here being for a MCP).
782
+
783
+ ### Contributing
784
+
785
+ Want to help with any of these items? See our [Contributing Guidelines](#-contributing) and pick an issue that interests you!
786
+
787
+ ---