@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.
Files changed (92) hide show
  1. package/README.md +52 -852
  2. package/dist/browser/core/baseProcessor.js +241 -0
  3. package/dist/browser/core/stringCasing.js +179 -0
  4. package/dist/browser/core/treeStructure.js +255 -0
  5. package/dist/browser/index.browser.js +73 -0
  6. package/dist/browser/processors/applePanelsProcessor.js +582 -0
  7. package/dist/browser/processors/astericsGridProcessor.js +1509 -0
  8. package/dist/browser/processors/dotProcessor.js +221 -0
  9. package/dist/browser/processors/gridset/commands.js +962 -0
  10. package/dist/browser/processors/gridset/crypto.js +53 -0
  11. package/dist/browser/processors/gridset/password.js +43 -0
  12. package/dist/browser/processors/gridset/pluginTypes.js +277 -0
  13. package/dist/browser/processors/gridset/resolver.js +137 -0
  14. package/dist/browser/processors/gridset/symbolAlignment.js +276 -0
  15. package/dist/browser/processors/gridset/symbols.js +421 -0
  16. package/dist/browser/processors/gridsetProcessor.js +2002 -0
  17. package/dist/browser/processors/obfProcessor.js +705 -0
  18. package/dist/browser/processors/opmlProcessor.js +274 -0
  19. package/dist/browser/types/aac.js +38 -0
  20. package/dist/browser/utilities/analytics/utils/idGenerator.js +89 -0
  21. package/dist/browser/utilities/translation/translationProcessor.js +200 -0
  22. package/dist/browser/utils/io.js +95 -0
  23. package/dist/browser/validation/baseValidator.js +156 -0
  24. package/dist/browser/validation/gridsetValidator.js +355 -0
  25. package/dist/browser/validation/obfValidator.js +500 -0
  26. package/dist/browser/validation/validationTypes.js +46 -0
  27. package/dist/cli/index.js +5 -5
  28. package/dist/core/analyze.d.ts +2 -2
  29. package/dist/core/analyze.js +2 -2
  30. package/dist/core/baseProcessor.d.ts +5 -4
  31. package/dist/core/baseProcessor.js +22 -27
  32. package/dist/core/treeStructure.d.ts +5 -5
  33. package/dist/core/treeStructure.js +1 -4
  34. package/dist/index.browser.d.ts +37 -0
  35. package/dist/index.browser.js +99 -0
  36. package/dist/index.d.ts +1 -48
  37. package/dist/index.js +1 -136
  38. package/dist/index.node.d.ts +48 -0
  39. package/dist/index.node.js +152 -0
  40. package/dist/processors/applePanelsProcessor.d.ts +5 -4
  41. package/dist/processors/applePanelsProcessor.js +58 -62
  42. package/dist/processors/astericsGridProcessor.d.ts +7 -6
  43. package/dist/processors/astericsGridProcessor.js +31 -42
  44. package/dist/processors/dotProcessor.d.ts +5 -4
  45. package/dist/processors/dotProcessor.js +25 -33
  46. package/dist/processors/excelProcessor.d.ts +4 -3
  47. package/dist/processors/excelProcessor.js +6 -3
  48. package/dist/processors/gridset/crypto.d.ts +18 -0
  49. package/dist/processors/gridset/crypto.js +57 -0
  50. package/dist/processors/gridset/helpers.d.ts +1 -1
  51. package/dist/processors/gridset/helpers.js +18 -8
  52. package/dist/processors/gridset/password.d.ts +20 -3
  53. package/dist/processors/gridset/password.js +17 -3
  54. package/dist/processors/gridset/wordlistHelpers.d.ts +3 -3
  55. package/dist/processors/gridset/wordlistHelpers.js +21 -20
  56. package/dist/processors/gridsetProcessor.d.ts +7 -12
  57. package/dist/processors/gridsetProcessor.js +116 -77
  58. package/dist/processors/obfProcessor.d.ts +9 -7
  59. package/dist/processors/obfProcessor.js +131 -56
  60. package/dist/processors/obfsetProcessor.d.ts +5 -4
  61. package/dist/processors/obfsetProcessor.js +10 -16
  62. package/dist/processors/opmlProcessor.d.ts +5 -4
  63. package/dist/processors/opmlProcessor.js +27 -34
  64. package/dist/processors/snapProcessor.d.ts +8 -7
  65. package/dist/processors/snapProcessor.js +15 -12
  66. package/dist/processors/touchchatProcessor.d.ts +8 -7
  67. package/dist/processors/touchchatProcessor.js +22 -17
  68. package/dist/types/aac.d.ts +0 -2
  69. package/dist/types/aac.js +2 -0
  70. package/dist/utils/io.d.ts +12 -0
  71. package/dist/utils/io.js +107 -0
  72. package/dist/validation/gridsetValidator.js +7 -7
  73. package/dist/validation/snapValidator.js +28 -35
  74. package/docs/BROWSER_USAGE.md +618 -0
  75. package/examples/README.md +77 -0
  76. package/examples/browser-test-server.js +81 -0
  77. package/examples/browser-test.html +331 -0
  78. package/examples/vitedemo/QUICKSTART.md +74 -0
  79. package/examples/vitedemo/README.md +157 -0
  80. package/examples/vitedemo/index.html +376 -0
  81. package/examples/vitedemo/package-lock.json +1221 -0
  82. package/examples/vitedemo/package.json +18 -0
  83. package/examples/vitedemo/src/main.ts +519 -0
  84. package/examples/vitedemo/test-files/example.dot +14 -0
  85. package/examples/vitedemo/test-files/example.grd +1 -0
  86. package/examples/vitedemo/test-files/example.gridset +0 -0
  87. package/examples/vitedemo/test-files/example.obz +0 -0
  88. package/examples/vitedemo/test-files/example.opml +18 -0
  89. package/examples/vitedemo/test-files/simple.obf +53 -0
  90. package/examples/vitedemo/tsconfig.json +24 -0
  91. package/examples/vitedemo/vite.config.ts +34 -0
  92. package/package.json +20 -4
package/README.md CHANGED
@@ -1,896 +1,96 @@
1
1
  # AACProcessors
2
2
 
3
- [![Coverage](https://img.shields.io/badge/coverage-74%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-495%20tests-brightgreen.svg)](./test)
6
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
3
+ A TypeScript library for reading, analyzing, translating, and converting AAC
4
+ (Augmentative and Alternative Communication) file formats. The package ships
5
+ as a dual build: a full Node.js entry and a browser-safe entry.
7
6
 
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
- - **Analyics & Metrics** - High-parity AAC effort metrics and clinical analysis tools
24
-
25
- ### **Advanced Capabilities**
26
-
27
- - πŸ”„ **Cross-format conversion** - Convert between any supported formats
28
- - 🌍 **Translation workflows** - Built-in i18n support with `processTexts()`
29
- - 🎨 **Comprehensive styling support** - Preserve visual appearance across formats
30
- - πŸ§ͺ **Property-based testing** - Robust validation with 140+ tests
31
- - βœ… **Format validation** - Spec-based validation for all supported formats
32
- - πŸ“Š **Clinical Metrics** - High-parity AAC effort algorithm (v0.2) and vocabulary coverage analysis
33
- - ⚑ **Performance optimized** - Memory-efficient processing of large files
34
- - πŸ›‘οΈ **Error recovery** - Graceful handling of corrupted data
35
- - πŸ”’ **Thread-safe** - Concurrent processing support
36
- - πŸ“Š **Comprehensive logging** - Detailed operation insights
37
-
38
- ---
39
-
40
- ## πŸ“¦ Installation
41
-
42
- ### From npm (Recommended)
7
+ ## Install
43
8
 
44
9
  ```bash
45
10
  npm install @willwade/aac-processors
46
11
  ```
47
12
 
48
- ### From Source
49
-
50
- ```bash
51
- git clone https://github.com/willwade/AACProcessors-nodejs.git
52
- cd AACProcessors-nodejs
53
- npm install
54
- npm run build
55
- ```
56
-
57
- ### Requirements
58
-
59
- - **Node.js** 20.0.0 or higher
60
- - **TypeScript** 5.5+ (for development)
61
-
62
- ---
63
-
64
- ## Using with Electron
65
-
66
- `better-sqlite3` is a native module and must be rebuilt against Electron's Node.js runtime. If you see a `NODE_MODULE_VERSION` mismatch error, rebuild after installing dependencies:
67
-
68
- ```bash
69
- npm install
70
- npx electron-rebuild
71
- ```
72
-
73
- Or add a postinstall hook so the rebuild happens automatically:
74
-
75
- ```json
76
- {
77
- "scripts": {
78
- "postinstall": "electron-builder install-app-deps"
79
- }
80
- }
81
- ```
82
-
83
- This step is only required for Electron apps; regular Node.js consumers do not need it.
13
+ ## Dual Build Targets
84
14
 
85
- ---
15
+ ### Node.js (default)
16
+ Full feature set, including filesystem access, SQLite-backed formats, and
17
+ ZIP/encrypted formats.
86
18
 
87
- ## Windows Data Paths
19
+ ```ts
20
+ import { getProcessor, SnapProcessor } from '@willwade/aac-processors';
88
21
 
89
- - **Grid 3 history**: `C:\Users\Public\Documents\Smartbox\Grid 3\Users\{username}\{langCode}\Phrases\history.sqlite`
90
- - **Grid 3 vocabularies**: `C:\Users\Public\Documents\Smartbox\Grid 3\Users\{username}\Grid Sets\`
91
- - **Snap vocabularies**: `C:\Users\{username}\AppData\Roaming\Tobii Dynavox\Snap Scene\Users\{userId}\` (`.sps`/`.spb`)
22
+ const processor = getProcessor('board.sps');
23
+ const tree = await processor.loadIntoTree('board.sps');
92
24
 
93
- ---
94
-
95
- ## πŸ”§ Quick Start
96
-
97
- ### Basic Usage (TypeScript)
98
-
99
- ```typescript
100
- import {
101
- getProcessor,
102
- DotProcessor,
103
- SnapProcessor,
104
- AstericsGridProcessor,
105
- } from "aac-processors";
106
-
107
- // Auto-detect processor by file extension
108
- const processor = getProcessor("communication-board.dot");
109
- const tree = processor.loadIntoTree("communication-board.dot");
110
-
111
- // Extract all text content
112
- const texts = processor.extractTexts("communication-board.dot");
113
- console.log("Found texts:", texts);
114
-
115
- // Direct processor usage
116
- const dotProcessor = new DotProcessor();
117
- const aacTree = dotProcessor.loadIntoTree("examples/example.dot");
118
- console.log("Pages:", Object.keys(aacTree.pages).length);
25
+ const snap = new SnapProcessor();
26
+ const texts = await snap.extractTexts('board.sps');
119
27
  ```
120
28
 
121
- ### Platform Support
122
-
123
- **AACProcessors is designed for Node.js environments only.** It requires Node.js v20+ and cannot run in browsers due to:
124
-
125
- - **File system access** - Required for reading/writing AAC files
126
- - **Native SQLite** - Used by Snap, TouchChat, and Analytics features
127
- - **Binary format processing** - ZIP, encrypted formats, etc.
29
+ ### Browser
30
+ Browser-safe entry that avoids Node-only dependencies. It expects `Buffer`,
31
+ `Uint8Array`, or `ArrayBuffer` inputs rather than file paths.
128
32
 
129
- **For browser-based AAC display**, consider these alternatives:
130
- - **obf-renderer** - Display OBF/OBZ files in web apps
131
- - **Arc Core** - Browser-based AAC communication
132
- - **Cboard** - Web-based AAC display system
33
+ ```ts
34
+ import { GridsetProcessor } from '@willwade/aac-processors/browser';
133
35
 
134
- This library focuses on **server-side file processing**, not client-side rendering.
135
-
136
- ### Button Filtering System
137
-
138
- 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.
139
-
140
- #### **Default Behavior**
141
-
142
- By default, the following buttons are filtered out during conversion:
143
-
144
- - **Navigation buttons**: Home, Back (toolbar navigation)
145
- - **System buttons**: Delete, Clear, Copy (text editing functions)
146
- - **Label-based filtering**: Buttons with common navigation terms
147
-
148
- #### **Configuration Options**
149
-
150
- ```typescript
151
- import { GridsetProcessor } from "aac-processors";
152
-
153
- // Default: exclude navigation/system buttons (recommended)
154
36
  const processor = new GridsetProcessor();
155
-
156
- // Preserve all buttons (legacy behavior)
157
- const processor = new GridsetProcessor({ preserveAllButtons: true });
158
-
159
- // Custom filtering
160
- const processor = new GridsetProcessor({
161
- excludeNavigationButtons: true,
162
- excludeSystemButtons: false,
163
- customButtonFilter: (button) => !button.label.includes("Settings"),
164
- });
37
+ const tree = await processor.loadIntoTree(gridsetUint8Array);
165
38
  ```
166
39
 
167
- #### **Why Filter Buttons?**
40
+ ## Supported Formats
168
41
 
169
- - **Cleaner conversions**: Navigation bars don't clutter converted vocabularies
170
- - **Format-appropriate**: Each AAC app handles navigation/system functions in their own UI
171
- - **Semantic-aware**: Uses proper semantic action detection, not just label matching
42
+ - Snap/SPS (Tobii Dynavox)
43
+ - Grid3/Gridset (Smartbox)
44
+ - TouchChat (PRC-Saltillo)
45
+ - OBF/OBZ (Open Board Format)
46
+ - OPML
47
+ - DOT (Graphviz)
48
+ - Apple Panels (macOS plist)
49
+ - Asterics Grid
50
+ - Excel export
172
51
 
173
- ### Translation Workflows
52
+ ## Translation Workflow
174
53
 
175
- All processors support built-in translation via the `processTexts()` method:
54
+ All processors implement `processTexts()` for translation use cases.
176
55
 
177
- ```typescript
178
- import { DotProcessor } from "aac-processors";
56
+ ```ts
57
+ import { DotProcessor } from '@willwade/aac-processors';
179
58
 
180
59
  const processor = new DotProcessor();
60
+ const texts = await processor.extractTexts('board.dot');
181
61
 
182
- // 1. Extract all translatable text
183
- const originalTexts = processor.extractTexts("board.dot");
184
-
185
- // 2. Create translation map (integrate with your translation service)
186
62
  const translations = new Map([
187
- ["Hello", "Hola"],
188
- ["Goodbye", "AdiΓ³s"],
189
- ["Food", "Comida"],
63
+ ['Hello', 'Hola'],
64
+ ['Food', 'Comida'],
190
65
  ]);
191
66
 
192
- // 3. Apply translations and save
193
- const translatedBuffer = processor.processTexts(
194
- "board.dot",
195
- translations,
196
- "board-spanish.dot",
197
- );
198
-
199
- console.log("Translation complete!");
200
- ```
201
-
202
- ### πŸ€– LLM-Based Translation with Symbol Preservation
203
-
204
- For advanced AI-powered translation that preserves symbol-to-word associations across languages, see the **[Translation Utilities Guide](./src/utilities/translation/README.md)**.
205
-
206
- **Features:**
207
- - 🧠 **Intelligent symbol mapping**: LLMs understand grammar, not just word position
208
- - 🎯 **Cross-format support**: Works with Gridset, OBF/OBZ, TouchChat, and Snap
209
- - πŸ”— **Symbol preservation**: Symbols stay attached to correct translated words
210
- - βœ… **Validated output**: Built-in validation catches translation errors
211
-
212
- **Quick Demo:**
213
- ```bash
214
- # Translate a Grid 3 file to Spanish using Gemini 2.0 Flash
215
- export GEMINI_API_KEY="your-key-here"
216
- node scripts/translation/gemini-translate-gridset.js "./tmp/Voco Chat.gridset" Spanish
217
- ```
218
-
219
- **Complete Example:**
220
- ```typescript
221
- import { GridsetProcessor } from "@willwade/aac-processors";
222
-
223
- const processor = new GridsetProcessor();
224
-
225
- // 1. Extract buttons with symbol information
226
- const buttons = processor.extractSymbolsForLLM("board.gridset");
227
-
228
- // 2. Create LLM prompt (or call your LLM API directly)
229
- // See: src/utilities/translation/README.md
230
-
231
- // 3. Apply translations with preserved symbols
232
- processor.processLLMTranslations(
233
- "board.gridset",
234
- llmTranslations,
235
- "board-spanish.gridset"
236
- );
237
- ```
238
-
239
- See **[scripts/translation/](./scripts/translation/)** for complete working examples with Gemini, GPT-4, and other LLMs.
240
-
241
- ### πŸ“Š AAC Analytics & Clinical Metrics
242
-
243
- The library includes an optional high-performance analytics engine for evaluating AAC board sets based on the **AAC Effort Algorithm (v0.2)**.
244
-
245
- #### **Key Metrics Features**
246
-
247
- - **Effort Scores**: Calculate the physical/cognitive cost of any word (Distance, Field Size, Motor Planning).
248
- - **Vocabulary Coverage**: Compare board sets against core vocabulary lists (e.g., Anderson & Bitner).
249
- - **Sentence Analysis**: Measure the effort required to construct common test sentences.
250
- - **Comparative Analysis**: Identify gaps and improvements between two pageset versions.
251
-
252
- For detailed documentation, see the **[AAC Metrics Guide](./src/utilities/analytics/docs/AAC_METRICS_GUIDE.md)** and **[Vocabulary Analysis Guide](./src/utilities/analytics/docs/VOCABULARY_ANALYSIS_GUIDE.md)**.
253
-
254
- ```typescript
255
- import { ObfsetProcessor, Analytics } from "@willwade/aac-processors";
256
-
257
- const processor = new ObfsetProcessor();
258
- const tree = processor.loadIntoTree("my_pageset.obfset");
259
-
260
- // Run clinical effort analysis
261
- const result = new Analytics.MetricsCalculator().analyze(tree);
262
- console.log(`Average Effort: ${result.total_words}`);
67
+ await processor.processTexts('board.dot', translations, 'board-es.dot');
263
68
  ```
264
69
 
265
- ### Format Validation
70
+ ## Documentation
266
71
 
267
- Validate AAC files against format specifications to ensure data integrity:
72
+ - API reference (TypeDoc): https://willwade.github.io/AACProcessors-nodejs/
73
+ - Metrics guide: `src/utilities/analytics/docs/AAC_METRICS_GUIDE.md`
74
+ - Vocabulary analysis guide: `src/utilities/analytics/docs/VOCABULARY_ANALYSIS_GUIDE.md`
268
75
 
269
- ```typescript
270
- import { validateFileOrBuffer, getValidatorForFile } from "@willwade/aac-processors/validation";
76
+ ## Examples and Scripts
271
77
 
272
- // Works in Node, Vite, and esbuild (pass Buffers from the browser/CLI)
273
- const fileName = "board.obf";
274
- const validator = getValidatorForFile(fileName);
275
- const bufferOrPath = new Uint8Array(await file.arrayBuffer()); // or fs path in Node
276
- const result = await validateFileOrBuffer(bufferOrPath, fileName);
78
+ - Code examples: `examples/`
79
+ - Utility scripts and workflows: `scripts/` (see `scripts/README.md`)
277
80
 
278
- console.log(result.valid, result.errors, result.warnings);
279
- result.results.forEach((check) => {
280
- if (!check.valid) console.log(`βœ— ${check.description}: ${check.error}`);
281
- });
282
- ```
283
-
284
- #### Using the CLI
81
+ ## Build, Lint, Test
285
82
 
286
83
  ```bash
287
- # Validate a file
288
- aacprocessors validate board.obf
289
-
290
- # JSON output
291
- aacprocessors validate board.obf --json
292
-
293
- # Quiet mode (just valid/invalid)
294
- aacprocessors validate board.gridset --quiet
295
-
296
- # Validate encrypted Gridset file
297
- aacprocessors validate board.gridsetx --gridset-password <password>
298
- ```
299
-
300
- #### What Gets Validated?
301
-
302
- - **OBF/OBZ**: Spec compliance (Open Board Format)
303
- - **Gridset/Gridsetx**: ZIP/XML structure, required Smartbox assets
304
- - **Snap**: ZIP/package content, settings/pages/images
305
- - **TouchChat**: ZIP structure, vocab metadata, nested boards
306
- - **Asterics (.grd)**: JSON parse, grids, elements, coordinates
307
- - **Excel (.xlsx/.xls)**: Workbook readability and worksheet content
308
- - **OPML**: XML validity and outline hierarchy
309
- - **DOT**: Graph nodes/edges present and text content
310
- - **Apple Panels (.plist/.ascconfig)**: PanelDefinitions presence and buttons
311
- - **OBFSet**: Bundled board layout checks
312
-
313
- - **Gridset**: XML structure
314
- - Required elements (gridset, pages, cells)
315
- - FixedCellSize configuration
316
- - Page and cell attributes
317
- - Image references
318
-
319
- - **Snap**: Package structure
320
- - ZIP package validity
321
- - Settings file format
322
- - Page/button configurations
323
-
324
- - **TouchChat**: XML structure
325
- - PageSet hierarchy
326
- - Button definitions
327
- - Navigation links
328
-
329
- ### Cross-Format Conversion
330
-
331
- Convert between any supported AAC formats:
332
-
333
- ```typescript
334
- import { DotProcessor, ObfProcessor } from "aac-processors";
335
-
336
- // Load from DOT format
337
- const dotProcessor = new DotProcessor();
338
- const tree = dotProcessor.loadIntoTree("communication-board.dot");
339
-
340
- // Save as OBF format
341
- const obfProcessor = new ObfProcessor();
342
- obfProcessor.saveFromTree(tree, "communication-board.obf");
343
-
344
- // The tree structure is preserved across formats
345
- console.log("Conversion complete!");
346
- ```
347
-
348
- ### Advanced Usage
349
-
350
- #### Asterics Grid with Audio Support
351
-
352
- ```typescript
353
- import { AstericsGridProcessor } from "aac-processors";
354
-
355
- // Load Asterics Grid file with audio support
356
- const processor = new AstericsGridProcessor({ loadAudio: true });
357
- const tree = processor.loadIntoTree("communication-board.grd");
358
-
359
- // Access audio recordings from buttons
360
- tree.traverse((page) => {
361
- page.buttons.forEach((button) => {
362
- if (button.audioRecording) {
363
- console.log(`Button "${button.label}" has audio recording`);
364
- console.log(
365
- `Audio data size: ${button.audioRecording.data?.length} bytes`,
366
- );
367
- }
368
- });
369
- });
370
-
371
- // Add audio to specific elements
372
- const audioData = Buffer.from(/* your audio data */);
373
- processor.addAudioToElement(
374
- "board.grd",
375
- "element-id",
376
- audioData,
377
- JSON.stringify({ mimeType: "audio/wav", durationMs: 2000 }),
378
- );
379
-
380
- // Create enhanced version with multiple audio recordings
381
- const audioMappings = new Map();
382
- audioMappings.set("element-1", { audioData: audioBuffer1 });
383
- audioMappings.set("element-2", { audioData: audioBuffer2 });
384
- processor.createAudioEnhancedGridFile(
385
- "source.grd",
386
- "enhanced.grd",
387
- audioMappings,
388
- );
389
- ```
390
-
391
- #### Excel Export for Vocabulary Analysis
392
-
393
- ```typescript
394
- import { ExcelProcessor, getProcessor } from "aac-processors";
395
-
396
- // Convert any AAC format to Excel for analysis
397
- const sourceProcessor = getProcessor("communication-board.gridset");
398
- const tree = sourceProcessor.loadIntoTree("communication-board.gridset");
399
-
400
- // Export to Excel with visual styling and navigation
401
- const excelProcessor = new ExcelProcessor();
402
- excelProcessor.saveFromTree(tree, "vocabulary-analysis.xlsx");
403
-
404
- // Each AAC page becomes an Excel worksheet tab
405
- // Buttons are represented as cells with:
406
- // - Cell value = button label
407
- // - Cell background = button background color
408
- // - Cell font color = button font color
409
- // - Cell comments = button message/vocalization
410
- // - Hyperlinks for navigation between worksheets
411
-
412
- // Optional: Navigation row with standard AAC buttons
413
- // (Home, Message Bar, Delete, Back, Clear) appears on each worksheet
414
- ```
415
-
416
- #### Working with the AACTree Structure
417
-
418
- ```typescript
419
- import { AACTree, AACPage, AACButton } from "aac-processors";
420
-
421
- // Create a communication board programmatically
422
- const tree = new AACTree();
423
-
424
- const homePage = new AACPage({
425
- id: "home",
426
- name: "Home Page",
427
- buttons: [],
428
- });
429
-
430
- const helloButton = new AACButton({
431
- id: "btn_hello",
432
- label: "Hello",
433
- message: "Hello, how are you?",
434
- type: "SPEAK",
435
- });
436
-
437
- const foodButton = new AACButton({
438
- id: "btn_food",
439
- label: "Food",
440
- message: "I want food",
441
- type: "NAVIGATE",
442
- targetPageId: "food_page",
443
- });
444
-
445
- homePage.addButton(helloButton);
446
- homePage.addButton(foodButton);
447
- tree.addPage(homePage);
448
-
449
- // Save to any format
450
- const processor = new DotProcessor();
451
- processor.saveFromTree(tree, "my-board.dot");
452
- ```
453
-
454
- #### Error Handling
455
-
456
- ```typescript
457
- import { DotProcessor } from "aac-processors";
458
-
459
- const processor = new DotProcessor();
460
-
461
- try {
462
- const tree = processor.loadIntoTree("potentially-corrupted.dot");
463
- console.log("Successfully loaded:", Object.keys(tree.pages).length, "pages");
464
- } catch (error) {
465
- console.error("Failed to load file:", error.message);
466
- // Processor handles corruption gracefully and provides meaningful errors
467
- }
468
- ```
469
-
470
- ### Styling Support
471
-
472
- The library now provides comprehensive styling support across all AAC formats, preserving visual appearance when converting between formats.
473
-
474
- #### Supported Styling Properties
475
-
476
- ```typescript
477
- interface AACStyle {
478
- backgroundColor?: string; // Button/page background color
479
- fontColor?: string; // Text color
480
- borderColor?: string; // Border color
481
- borderWidth?: number; // Border thickness
482
- fontSize?: number; // Font size in pixels
483
- fontFamily?: string; // Font family name
484
- fontWeight?: string; // "normal" | "bold"
485
- fontStyle?: string; // "normal" | "italic"
486
- textUnderline?: boolean; // Text underline
487
- labelOnTop?: boolean; // Label position (TouchChat)
488
- transparent?: boolean; // Transparent background
489
- }
490
- ```
491
-
492
- #### Creating Styled AAC Content
493
-
494
- ```typescript
495
- import { AACTree, AACPage, AACButton } from "aac-processors";
496
-
497
- // Create a page with styling
498
- const page = new AACPage({
499
- id: "main-page",
500
- name: "Main Communication Board",
501
- grid: [],
502
- buttons: [],
503
- parentId: null,
504
- style: {
505
- backgroundColor: "#f0f8ff",
506
- fontFamily: "Arial",
507
- fontSize: 16,
508
- },
509
- });
510
-
511
- // Create buttons with comprehensive styling
512
- const speakButton = new AACButton({
513
- id: "speak-btn-1",
514
- label: "Hello",
515
- message: "Hello, how are you?",
516
- type: "SPEAK",
517
- action: null,
518
- style: {
519
- backgroundColor: "#4CAF50",
520
- fontColor: "#ffffff",
521
- borderColor: "#45a049",
522
- borderWidth: 2,
523
- fontSize: 18,
524
- fontFamily: "Helvetica",
525
- fontWeight: "bold",
526
- labelOnTop: true,
527
- },
528
- });
529
-
530
- const navButton = new AACButton({
531
- id: "nav-btn-1",
532
- label: "More",
533
- message: "Navigate to more options",
534
- type: "NAVIGATE",
535
- targetPageId: "more-page",
536
- action: {
537
- type: "NAVIGATE",
538
- targetPageId: "more-page",
539
- },
540
- style: {
541
- backgroundColor: "#2196F3",
542
- fontColor: "#ffffff",
543
- borderColor: "#1976D2",
544
- borderWidth: 1,
545
- fontSize: 16,
546
- fontStyle: "italic",
547
- transparent: false,
548
- },
549
- });
550
-
551
- page.addButton(speakButton);
552
- page.addButton(navButton);
553
-
554
- const tree = new AACTree();
555
- tree.addPage(page);
556
-
557
- // Save with styling preserved
558
- import { SnapProcessor } from "aac-processors";
559
- const processor = new SnapProcessor();
560
- processor.saveFromTree(tree, "styled-board.spb");
561
- ```
562
-
563
- #### Format-Specific Styling Support
564
-
565
- | Format | Background | Font | Border | Advanced |
566
- | ----------------- | ---------- | ------------ | ------- | ------------------------------- |
567
- | **Snap/SPS** | βœ… Full | βœ… Full | βœ… Full | βœ… All properties |
568
- | **TouchChat** | βœ… Full | βœ… Full | βœ… Full | βœ… Label position, transparency |
569
- | **OBF/OBZ** | βœ… Yes | ❌ No | βœ… Yes | ❌ Basic only |
570
- | **Grid3** | βœ… Yes | βœ… Yes | βœ… Yes | βœ… Style references |
571
- | **Asterics Grid** | βœ… Yes | βœ… Yes | βœ… Yes | βœ… Metadata-based |
572
- | **Apple Panels** | βœ… Yes | βœ… Size only | ❌ No | βœ… Display weight |
573
- | **Dot** | ❌No | ❌ Yes | ❌ No | ❌ Basic only |
574
- | **OPML** | ❌No | ❌ Yes | ❌ No | ❌ Basic only |
575
- | **Excel** | βœ… Yes | βœ… Size only | ❌ No | βœ… Display weight |
576
-
577
- #### Cross-Format Styling Conversion
578
-
579
- ```typescript
580
- import { getProcessor } from "aac-processors";
581
-
582
- // Load styled content from TouchChat
583
- const touchChatProcessor = getProcessor("input.ce");
584
- const styledTree = touchChatProcessor.loadIntoTree("input.ce");
585
-
586
- // Convert to Snap format while preserving styling
587
- const snapProcessor = getProcessor("output.spb");
588
- snapProcessor.saveFromTree(styledTree, "output.spb");
589
-
590
- // Styling information is automatically mapped between formats
591
- console.log("Styling preserved across formats!");
592
- ```
593
-
594
- ### CLI Usage
595
-
596
- The CLI provides three main commands for working with AAC files:
597
-
598
- #### **Extract Text Content**
599
-
600
- ```bash
601
- # Extract all text from an AAC file
602
- npx aac-processors extract examples/example.dot
603
-
604
- # With format specification and verbose output
605
- npx aac-processors extract examples/example.sps --format snap --verbose
606
- ```
607
-
608
- #### **Convert Between Formats**
609
-
610
- ```bash
611
- # Convert from one format to another (format auto-detected from input extension)
612
- npx aac-processors convert input.sps output.obf --format obf
613
-
614
- # Convert TouchChat to Snap format
615
- npx aac-processors convert communication.ce backup.spb --format snap
616
-
617
- # Convert any AAC format to Excel for vocabulary analysis
618
- npx aac-processors convert input.gridset vocabulary-analysis.xlsx --format xlsx
619
-
620
- # Convert with button filtering options
621
- npx aac-processors convert input.gridset output.grd --format grd --preserve-all-buttons
622
- npx aac-processors convert input.ce output.spb --format snap --exclude-buttons "settings,menu"
623
- npx aac-processors convert input.obf output.gridset --format gridset --no-exclude-system
624
- ```
625
-
626
- #### **Analyze File Structure**
627
-
628
- ```bash
629
- # Get detailed file information in JSON format
630
- npx aac-processors analyze examples/example.ce
631
-
632
- # Get human-readable file information
633
- npx aac-processors analyze examples/example.gridset --pretty
634
- ```
635
-
636
- #### **Available Options**
637
-
638
- **General Options:**
639
-
640
- - `--format <format>` - Specify format type (auto-detected if not provided)
641
- - `--pretty` - Human-readable output (analyze command)
642
- - `--verbose` - Detailed output (extract command)
643
- - `--quiet` - Minimal output (extract command)
644
- - `--gridset-password <password>` - Password for encrypted Grid 3 archives (`.gridsetx`)
645
-
646
- **Button Filtering Options:**
647
-
648
- - `--preserve-all-buttons` - Preserve all buttons including navigation/system buttons
649
- - `--no-exclude-navigation` - Don't exclude navigation buttons (Home, Back)
650
- - `--no-exclude-system` - Don't exclude system buttons (Delete, Clear, etc.)
651
- - `--exclude-buttons <list>` - Comma-separated list of button labels/terms to exclude
652
-
653
- **Examples:**
654
-
655
- ```bash
656
- # Extract text with all buttons preserved
657
- npx aac-processors extract input.ce --preserve-all-buttons --verbose
658
-
659
- # Convert excluding only custom buttons
660
- npx aac-processors convert input.gridset output.grd --format grd --exclude-buttons "settings,help,menu"
661
-
662
- # Analyze with navigation buttons excluded but system buttons preserved
663
- npx aac-processors analyze input.spb --no-exclude-system --pretty
664
- ```
665
-
666
- ---
667
-
668
- ## πŸ“š API Reference
669
-
670
- ### Core Classes
671
-
672
- #### `getProcessor(filePathOrExtension: string): BaseProcessor`
673
-
674
- Factory function that returns the appropriate processor for a file extension.
675
-
676
- ```typescript
677
- const processor = getProcessor(".dot"); // Returns DotProcessor
678
- const processor2 = getProcessor("file.obf"); // Returns ObfProcessor
679
- ```
680
-
681
- #### `BaseProcessor`
682
-
683
- Abstract base class for all processors with these key methods:
684
-
685
- - `loadIntoTree(filePathOrBuffer: string | Buffer): AACTree` - Load file into tree structure
686
- - `saveFromTree(tree: AACTree, outputPath: string): void` - Save tree to file
687
- - `extractTexts(filePathOrBuffer: string | Buffer): string[]` - Extract all text content
688
- - `processTexts(input: string | Buffer, translations: Map<string, string>, outputPath: string): Buffer` - Apply translations
689
-
690
- #### `AACTree`
691
-
692
- Core data structure representing a communication board:
693
-
694
- ```typescript
695
- interface AACTree {
696
- pages: Record<string, AACPage>;
697
- rootId?: string;
698
- addPage(page: AACPage): void;
699
- traverse(callback: (page: AACPage) => void): void;
700
- }
701
- ```
702
-
703
- #### `AACPage`
704
-
705
- Represents a single page/screen in a communication board:
706
-
707
- ```typescript
708
- interface AACPage {
709
- id: string;
710
- name: string;
711
- buttons: AACButton[];
712
- parentId?: string;
713
- addButton(button: AACButton): void;
714
- }
715
- ```
716
-
717
- #### `AACButton`
718
-
719
- Represents a button/cell in a communication board:
720
-
721
- ```typescript
722
- interface AACButton {
723
- id: string;
724
- label: string;
725
- message?: string;
726
- type: "SPEAK" | "NAVIGATE";
727
- targetPageId?: string; // For navigation buttons
728
- }
729
- ```
730
-
731
- ### Supported Processors
732
-
733
- | Processor | File Extensions | Description |
734
- | ----------------------- | ----------------------- | ----------------------------- |
735
- | `DotProcessor` | `.dot` | Graphviz DOT format |
736
- | `OpmlProcessor` | `.opml` | OPML hierarchical format |
737
- | `ObfProcessor` | `.obf`, `.obz` | Open Board Format (JSON/ZIP) |
738
- | `SnapProcessor` | `.sps`, `.spb` | Tobii Dynavox Snap format |
739
- | `GridsetProcessor` | `.gridset`, `.gridsetx` | Smartbox Grid 3 format |
740
- | `TouchChatProcessor` | `.ce` | PRC-Saltillo TouchChat format |
741
- | `ApplePanelsProcessor` | `.plist` | iOS Apple Panels format |
742
- | `AstericsGridProcessor` | `.grd` | Asterics Grid native format |
743
- | `ExcelProcessor` | `.xlsx` | Microsoft Excel format |
744
-
745
- ---
746
-
747
- ## πŸ§ͺ Testing & Quality
748
-
749
- This library maintains **65% test coverage** with **111 comprehensive tests** including:
750
-
751
- - **Unit tests** for all processors and core functionality
752
- - **Integration tests** for cross-format workflows
753
- - **Property-based tests** using fast-check for edge case discovery
754
- - **Performance tests** for memory usage and large file handling
755
- - **Error handling tests** for corrupted data and edge cases
756
-
757
- ### Running Tests
758
-
759
- ```bash
760
- # Run all tests (automatically builds first)
761
- npm test
762
-
763
- # Run with coverage report (automatically builds first)
764
- npm run test:coverage
765
-
766
- # Run tests in watch mode (automatically builds first)
767
- npm run test:watch
768
-
769
- # Generate detailed coverage analysis
770
- npm run coverage:report
771
- ```
772
-
773
- **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.
774
-
775
- ### πŸ› οΈ Utility Scripts
776
-
777
- A wide range of utility scripts for batch processing, audio generation, and advanced analysis are available in the **[scripts/](./scripts/README.md)** directory. These include:
778
-
779
- - **Analysis**: Pageset reporting and vocabulary extraction.
780
- - **Audio**: Automated TTS generation and audio-enhanced pageset creation.
781
- - **Conversion**: TSV-to-Gridset and other format-shifting tools.
782
- - **Translation**: Batch translation workflows using Google, Azure, and Gemini.
783
-
784
- ### Development Commands
785
-
786
- ```bash
787
- # Build TypeScript
788
- npm run build
789
-
790
- # Watch mode for development
791
- npm run build:watch
792
-
793
- # Lint code
84
+ npm run build:all
794
85
  npm run lint
795
-
796
- # Format code
797
- npm run format
798
-
799
- # Type checking
800
- npm run type-check
86
+ npm test
801
87
  ```
802
88
 
803
- ---
804
-
805
- ## 🀝 Contributing
89
+ ## Electron Note
806
90
 
807
- We welcome contributions! Please read our [Contributor License Agreement (CLA)](CLA.md) before you get started.
808
-
809
- 1. Fork the repository
810
- 2. Create a feature branch: `git checkout -b feature/amazing-feature`
811
- 3. Make your changes with tests
812
- 4. Run the test suite: `npm test`
813
- 5. Commit your changes: `git commit -m 'Add amazing feature'`
814
- 6. Push to the branch: `git push origin feature/amazing-feature`
815
- 7. Open a Pull Request
816
-
817
- ### Development Setup
91
+ `better-sqlite3` is a native dependency. For Electron, rebuild it against the
92
+ Electron runtime:
818
93
 
819
94
  ```bash
820
- git clone https://github.com/willwade/AACProcessors-nodejs.git
821
- cd AACProcessors-nodejs
822
- npm install
823
- npm run build
824
- npm test
95
+ npx electron-rebuild
825
96
  ```
826
-
827
- ### Environment Variables
828
-
829
- - Copy the template: `cp .envrc.example .envrc`
830
- - Fill in your own API keys locally; `.envrc` is ignored to prevent accidental commits
831
- - If you rotate keys, update only your local `.envrc`β€”never commit real secrets
832
-
833
- ### Publishing to npm
834
-
835
- - The repository keeps `package.json` at `0.0.0-development`; release tags control the published version.
836
- - Create a GitHub release with a semantic tag (e.g. `v2.1.0`). Publishing only runs for non-prerelease tags.
837
- - The workflow (`.github/workflows/publish.yml`) automatically installs dependencies, rewrites the package version from the tag, and runs the standard publish pipeline.
838
-
839
- ---
840
-
841
- ## πŸ“„ License
842
-
843
- MIT License - see [LICENSE](LICENSE) file for details.
844
-
845
- ---
846
-
847
- ## πŸ™ Credits
848
-
849
- Created by **Will Wade** and contributors.
850
-
851
- Inspired by the Python AACProcessors project
852
-
853
- ### Related Projects
854
-
855
- - [AACProcessors (Python)](https://github.com/willwade/AACProcessors) - Original Python implementation
856
- - [Open Board Format](https://www.openboardformat.org/) - Open standard for communication boards
857
-
858
- ---
859
-
860
- ## πŸ“ž Support
861
-
862
- - πŸ› **Bug Reports**: [GitHub Issues](https://github.com/willwade/AACProcessors-nodejs/issues)
863
- - πŸ’¬ **Discussions**: [GitHub Discussions](https://github.com/willwade/AACProcessors-nodejs/discussions)
864
- - πŸ“§ **Email**: wwade@acecentre.org.uk
865
-
866
- ---
867
-
868
- ## πŸ“‹ TODO & Roadmap
869
-
870
- ### πŸ”₯ Critical Priority (Immediate Action Required)
871
-
872
- - [ ] **Road Testing** - Perform comprehensive layout and formatting validation across diverse pagesets to verify conversion fidelity.
873
- - [ ] **Fix audio persistence issues** - Resolve functional audio recording persistence in `SnapProcessor` save/load cycle (5 failing tests remaining).
874
- - [x] **Access Method Modeling** - Support for switch scanning (linear, row-column, block) integrated into AAC metrics.
875
-
876
- ### 🚨 High Priority (Next Sprint)
877
-
878
- - [ ] **Complete SnapProcessor coverage** (currently ~60%) - Reach >75% coverage by adding comprehensive audio handling and database corruption tests.
879
- - [ ] **Symbol System Rethink** - Explore treating "Symbols" as a first-class entity (alongside Pages/Buttons) to support richer metadata (library IDs, synonyms, multi-lang names).
880
- - [ ] **Language & Locale Persistence** - Ensure current language and locale information is correctly preserved and bubbled up to the `AACTree` level.
881
-
882
- ### ⚠️ Medium Priority
883
-
884
- - [ ] **Adaptive Metrics** - Expand scanning analysis to include dwell times and more complex switch logic configurations.
885
-
886
- ### Low Priority
887
-
888
- - [ ] **Batch processing CLI** - Process multiple files/directories in parallel.
889
-
890
- ### Contributing
891
-
892
- Want to help with any of these items? See our [Contributing Guidelines](#-contributing) and pick an issue that interests you!
893
-
894
- ### Credits
895
-
896
- Some of the OBF work is directly from https://github.com/open-aac/obf and https://github.com/open-aac/aac-metrics - OBLA too https://www.openboardformat.org/logs