@willwade/aac-processors 0.0.12 → 0.0.14

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 (60) hide show
  1. package/README.md +46 -44
  2. package/dist/core/baseProcessor.d.ts +41 -0
  3. package/dist/core/baseProcessor.js +41 -0
  4. package/dist/core/treeStructure.d.ts +35 -2
  5. package/dist/core/treeStructure.js +18 -3
  6. package/dist/index.d.ts +2 -2
  7. package/dist/index.js +2 -2
  8. package/dist/processors/astericsGridProcessor.d.ts +15 -0
  9. package/dist/processors/astericsGridProcessor.js +17 -0
  10. package/dist/processors/gridset/helpers.d.ts +4 -1
  11. package/dist/processors/gridset/helpers.js +4 -0
  12. package/dist/processors/gridset/pluginTypes.js +51 -50
  13. package/dist/processors/gridset/symbolAlignment.d.ts +125 -0
  14. package/dist/processors/gridset/symbolAlignment.js +283 -0
  15. package/dist/processors/gridset/symbolExtractor.js +3 -2
  16. package/dist/processors/gridset/symbolSearch.js +9 -7
  17. package/dist/processors/gridsetProcessor.d.ts +26 -0
  18. package/dist/processors/gridsetProcessor.js +178 -25
  19. package/dist/processors/obfProcessor.d.ts +26 -0
  20. package/dist/processors/obfProcessor.js +94 -1
  21. package/dist/processors/snap/helpers.d.ts +5 -1
  22. package/dist/processors/snap/helpers.js +5 -0
  23. package/dist/processors/snapProcessor.d.ts +2 -0
  24. package/dist/processors/snapProcessor.js +156 -5
  25. package/dist/processors/touchchatProcessor.d.ts +26 -0
  26. package/dist/processors/touchchatProcessor.js +106 -6
  27. package/dist/types/aac.d.ts +63 -0
  28. package/dist/types/aac.js +33 -0
  29. package/dist/{optional → utilities}/analytics/history.d.ts +12 -1
  30. package/dist/{optional → utilities}/analytics/index.d.ts +2 -0
  31. package/dist/{optional → utilities}/analytics/index.js +6 -1
  32. package/dist/{optional → utilities}/analytics/metrics/comparison.js +8 -4
  33. package/dist/{optional → utilities}/analytics/metrics/core.d.ts +9 -0
  34. package/dist/{optional → utilities}/analytics/metrics/core.js +190 -37
  35. package/dist/{optional → utilities}/analytics/metrics/effort.d.ts +10 -0
  36. package/dist/{optional → utilities}/analytics/metrics/effort.js +13 -0
  37. package/dist/utilities/analytics/metrics/obl-types.d.ts +93 -0
  38. package/dist/utilities/analytics/metrics/obl-types.js +7 -0
  39. package/dist/utilities/analytics/metrics/obl.d.ts +40 -0
  40. package/dist/utilities/analytics/metrics/obl.js +287 -0
  41. package/dist/{optional → utilities}/analytics/metrics/vocabulary.js +6 -4
  42. package/dist/{optional → utilities}/symbolTools.js +13 -16
  43. package/dist/utilities/translation/translationProcessor.d.ts +119 -0
  44. package/dist/utilities/translation/translationProcessor.js +204 -0
  45. package/dist/validation/gridsetValidator.js +10 -0
  46. package/package.json +1 -1
  47. /package/dist/{optional → utilities}/analytics/history.js +0 -0
  48. /package/dist/{optional → utilities}/analytics/metrics/comparison.d.ts +0 -0
  49. /package/dist/{optional → utilities}/analytics/metrics/index.d.ts +0 -0
  50. /package/dist/{optional → utilities}/analytics/metrics/index.js +0 -0
  51. /package/dist/{optional → utilities}/analytics/metrics/sentence.d.ts +0 -0
  52. /package/dist/{optional → utilities}/analytics/metrics/sentence.js +0 -0
  53. /package/dist/{optional → utilities}/analytics/metrics/types.d.ts +0 -0
  54. /package/dist/{optional → utilities}/analytics/metrics/types.js +0 -0
  55. /package/dist/{optional → utilities}/analytics/metrics/vocabulary.d.ts +0 -0
  56. /package/dist/{optional → utilities}/analytics/reference/index.d.ts +0 -0
  57. /package/dist/{optional → utilities}/analytics/reference/index.js +0 -0
  58. /package/dist/{optional → utilities}/analytics/utils/idGenerator.d.ts +0 -0
  59. /package/dist/{optional → utilities}/analytics/utils/idGenerator.js +0 -0
  60. /package/dist/{optional → utilities}/symbolTools.d.ts +0 -0
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # AACProcessors
2
2
 
3
- [![Coverage](https://img.shields.io/badge/coverage-77%25-green.svg)](./coverage)
3
+ [![Coverage](https://img.shields.io/badge/coverage-74%25-green.svg)](./coverage)
4
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)
5
+ [![Tests](https://img.shields.io/badge/tests-495%20tests-brightgreen.svg)](./test)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
7
 
8
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.
@@ -20,6 +20,7 @@ A comprehensive **TypeScript library** for processing AAC (Augmentative and Alte
20
20
  - **Apple Panels** (MacOS) - Plist format support
21
21
  - **Asterics Grid** - Native Asterics Grid format with audio
22
22
  - **Excel** - Export to Microsoft Excel for vocabulary analysis
23
+ - **Analyics & Metrics** - High-parity AAC effort metrics and clinical analysis tools
23
24
 
24
25
  ### **Advanced Capabilities**
25
26
 
@@ -28,6 +29,7 @@ A comprehensive **TypeScript library** for processing AAC (Augmentative and Alte
28
29
  - 🎨 **Comprehensive styling support** - Preserve visual appearance across formats
29
30
  - 🧪 **Property-based testing** - Robust validation with 140+ tests
30
31
  - ✅ **Format validation** - Spec-based validation for all supported formats
32
+ - 📊 **Clinical Metrics** - High-parity AAC effort algorithm (v0.2) and vocabulary coverage analysis
31
33
  - ⚡ **Performance optimized** - Memory-efficient processing of large files
32
34
  - 🛡️ **Error recovery** - Graceful handling of corrupted data
33
35
  - 🔒 **Thread-safe** - Concurrent processing support
@@ -192,6 +194,30 @@ const translatedBuffer = processor.processTexts(
192
194
  console.log("Translation complete!");
193
195
  ```
194
196
 
197
+ ### 📊 AAC Analytics & Clinical Metrics
198
+
199
+ The library includes an optional high-performance analytics engine for evaluating AAC board sets based on the **AAC Effort Algorithm (v0.2)**.
200
+
201
+ #### **Key Metrics Features**
202
+
203
+ - **Effort Scores**: Calculate the physical/cognitive cost of any word (Distance, Field Size, Motor Planning).
204
+ - **Vocabulary Coverage**: Compare board sets against core vocabulary lists (e.g., Anderson & Bitner).
205
+ - **Sentence Analysis**: Measure the effort required to construct common test sentences.
206
+ - **Comparative Analysis**: Identify gaps and improvements between two pageset versions.
207
+
208
+ For detailed documentation, see the **[AAC Metrics Guide](./src/optional/analytics/docs/AAC_METRICS_GUIDE.md)** and **[Vocabulary Analysis Guide](./src/optional/analytics/docs/VOCABULARY_ANALYSIS_GUIDE.md)**.
209
+
210
+ ```typescript
211
+ import { ObfsetProcessor, Analytics } from "@willwade/aac-processors";
212
+
213
+ const processor = new ObfsetProcessor();
214
+ const tree = processor.loadIntoTree("my_pageset.obfset");
215
+
216
+ // Run clinical effort analysis
217
+ const result = new Analytics.MetricsCalculator().analyze(tree);
218
+ console.log(`Average Effort: ${result.total_words}`);
219
+ ```
220
+
195
221
  ### Format Validation
196
222
 
197
223
  Validate AAC files against format specifications to ensure data integrity:
@@ -710,6 +736,15 @@ npm run coverage:report
710
736
 
711
737
  **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.
712
738
 
739
+ ### 🛠️ Utility Scripts
740
+
741
+ 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:
742
+
743
+ - **Analysis**: Pageset reporting and vocabulary extraction.
744
+ - **Audio**: Automated TTS generation and audio-enhanced pageset creation.
745
+ - **Conversion**: TSV-to-Gridset and other format-shifting tools.
746
+ - **Translation**: Batch translation workflows using Google, Azure, and Gemini.
747
+
713
748
  ### Development Commands
714
749
 
715
750
  ```bash
@@ -798,57 +833,24 @@ Inspired by the Python AACProcessors project
798
833
 
799
834
  ### 🔥 Critical Priority (Immediate Action Required)
800
835
 
801
- - [ ] **Fix audio persistence issues** (5 tests failing) - Resolve functional audio recording persistence in SnapProcessor save/load cycle (reduced from 21 failing tests)
802
- - [ ] **Resolve database constraint violations** - Fix UNIQUE constraint failures in Page.Id and buttons.id when processing real-world data files (blocks production usage)
803
- - [ ] **Fix Grid3 layout issues** - Grid sizes not reliable and X,Y positions incorrect, particularly affecting Grid3 processor functionality
836
+ - [ ] **Road Testing** - Perform comprehensive layout and formatting validation across diverse pagesets to verify conversion fidelity.
837
+ - [ ] **Fix audio persistence issues** - Resolve functional audio recording persistence in `SnapProcessor` save/load cycle (5 failing tests remaining).
838
+ - [x] **Access Method Modeling** - Support for switch scanning (linear, row-column, block) integrated into AAC metrics.
804
839
 
805
840
  ### 🚨 High Priority (Next Sprint)
806
841
 
807
- - [ ] **Complete SnapProcessor coverage** (currently 48.32% - lowest processor) - Add comprehensive audio handling, database corruption tests, and SQLite schema validation to reach >75% coverage
808
- - [ ] **Reduce remaining linting issues** (123 remaining) - Address TypeScript eslint errors and warnings in test files and less critical areas
809
- - [ ] **Improve GridsetProcessor coverage** (currently 71.69%) - Enhance ZIP handling and complex Grid3 archive support to reach >80% coverage
810
-
811
- ### ⚠️ Medium Priority (Following Sprint)
842
+ - [ ] **Complete SnapProcessor coverage** (currently ~60%) - Reach >75% coverage by adding comprehensive audio handling and database corruption tests.
843
+ - [ ] **Symbol System Rethink** - Explore treating "Symbols" as a first-class entity (alongside Pages/Buttons) to support richer metadata (library IDs, synonyms, multi-lang names).
844
+ - [ ] **Language & Locale Persistence** - Ensure current language and locale information is correctly preserved and bubbled up to the `AACTree` level.
812
845
 
813
- - [ ] **Improve GridsetProcessor coverage** (currently 71.69%) - Enhance ZIP handling and complex Grid3 archive support to reach >80% coverage
814
- - [ ] **Improve AstericsGridProcessor coverage** (currently 62.5%) - Add comprehensive tests for Asterics Grid format processing to reach >80% coverage
815
- - [ ] **Add Symbol Tools coverage** (currently 0%) - Implement tests for PCS and ARASAAC symbol lookups to reach >70% coverage
816
- - [ ] **Fix property-based test failures** - Resolve TypeScript interface compatibility issues in edge case generators
846
+ ### ⚠️ Medium Priority
817
847
 
818
- ### Medium Priority
819
-
820
- - [ ] **Performance optimization** - Optimize memory usage for very large communication boards (1000+ buttons)
821
- - [ ] **Add GridsetProcessor ZIP handling** - Improve support for complex Grid3 ZIP archives
822
- - [ ] **Enhance error recovery** - Better handling of partially corrupted database files
823
- - [ ] **Add streaming support** - Process very large files without loading entirely into memory
824
- - [ ] **Improve translation workflows** - Add support for translation service integrations (Google Translate, Azure, etc.)
825
- - [ ] **Add symbol library integration** - Complete implementation of PCS, ARASAAC symbol lookups
848
+ - [ ] **Adaptive Metrics** - Expand scanning analysis to include dwell times and more complex switch logic configurations.
826
849
 
827
850
  ### Low Priority
828
851
 
829
- - [ ] **Add more AAC formats** - Look for other common AAC formats to add
830
- - [ ] **Plugin system** - Allow third-party processors and extensions
831
- - [ ] **Batch processing CLI** - Process multiple files in parallel
832
- - [ ] **Configuration file support** - Allow .aacprocessors.json config files
833
-
834
- ### Testing & Quality
835
-
836
- - [ ] **Reach 80%+ test coverage** - Current: 65.15% (target: 80%+)
837
- - [ ] **Add mutation testing** - Use Stryker.js for mutation testing
838
- - [ ] **Add benchmark suite** - Performance regression testing
839
- - [ ] **CI/CD improvements** - Add automated releases and npm publishing
840
- - [ ] **Documentation improvements** - Add more real-world examples and tutorials
841
-
842
- ## More enhancements
843
-
844
- - Much more effort put into fixing the layout issues. Grid sizes are not reliably and X, Y positions too. Particularly in the Grid3
845
- - 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.
846
- - Current language and locale information of aac pageset
847
- - 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.
848
- - 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).
852
+ - [ ] **Batch processing CLI** - Process multiple files/directories in parallel.
849
853
 
850
854
  ### Contributing
851
855
 
852
856
  Want to help with any of these items? See our [Contributing Guidelines](#-contributing) and pick an issue that interests you!
853
-
854
- ---
@@ -1,3 +1,44 @@
1
+ /**
2
+ * Base Processor for AAC File Formats
3
+ *
4
+ * This module provides base functionality for processing AAC (Augmentative and Alternative
5
+ * Communication) files across various formats (gridset, OBF, Snap, TouchChat, etc.).
6
+ *
7
+ * ## LLM-Based Translation with Symbol Preservation
8
+ *
9
+ * All processor formats support LLM-based translation that preserves symbol-to-word
10
+ * associations across languages. This is critical for AAC systems where visual symbols
11
+ * are attached to specific words.
12
+ *
13
+ * ### Usage Example:
14
+ *
15
+ * ```typescript
16
+ * import { extractAllButtonsForTranslation, createTranslationPrompt } from '../optional/translation/translationProcessor';
17
+ *
18
+ * // 1. Extract buttons from your format
19
+ * const buttons = extractAllButtonsForTranslation(myFormatButtons, (button) => ({
20
+ * pageId: button.pageId,
21
+ * pageName: button.pageName
22
+ * }));
23
+ *
24
+ * // 2. Create prompt for LLM
25
+ * const prompt = createTranslationPrompt(buttons, 'Spanish');
26
+ *
27
+ * // 3. Send to LLM (Gemini, GPT, etc.) and get response
28
+ * const llmResponse = await callLLMAPI(prompt);
29
+ *
30
+ * // 4. Apply translations to your format
31
+ * processor.processLLMTranslations(filePath, llmResponse, outputPath);
32
+ * ```
33
+ *
34
+ * ### Format-Specific Implementation:
35
+ *
36
+ * Each processor should implement:
37
+ * - `extractSymbolsForLLM()` - Uses extractAllButtonsForTranslation() utility
38
+ * - `processLLMTranslations()` - Applies translations using format-specific logic
39
+ *
40
+ * See `src/utilities/translation/translationProcessor.ts` for shared utilities.
41
+ */
1
42
  import { AACTree, AACButton } from './treeStructure';
2
43
  import { StringCasing } from './stringCasing';
3
44
  import { ValidationResult } from '../validation/validationTypes';
@@ -1,4 +1,45 @@
1
1
  "use strict";
2
+ /**
3
+ * Base Processor for AAC File Formats
4
+ *
5
+ * This module provides base functionality for processing AAC (Augmentative and Alternative
6
+ * Communication) files across various formats (gridset, OBF, Snap, TouchChat, etc.).
7
+ *
8
+ * ## LLM-Based Translation with Symbol Preservation
9
+ *
10
+ * All processor formats support LLM-based translation that preserves symbol-to-word
11
+ * associations across languages. This is critical for AAC systems where visual symbols
12
+ * are attached to specific words.
13
+ *
14
+ * ### Usage Example:
15
+ *
16
+ * ```typescript
17
+ * import { extractAllButtonsForTranslation, createTranslationPrompt } from '../optional/translation/translationProcessor';
18
+ *
19
+ * // 1. Extract buttons from your format
20
+ * const buttons = extractAllButtonsForTranslation(myFormatButtons, (button) => ({
21
+ * pageId: button.pageId,
22
+ * pageName: button.pageName
23
+ * }));
24
+ *
25
+ * // 2. Create prompt for LLM
26
+ * const prompt = createTranslationPrompt(buttons, 'Spanish');
27
+ *
28
+ * // 3. Send to LLM (Gemini, GPT, etc.) and get response
29
+ * const llmResponse = await callLLMAPI(prompt);
30
+ *
31
+ * // 4. Apply translations to your format
32
+ * processor.processLLMTranslations(filePath, llmResponse, outputPath);
33
+ * ```
34
+ *
35
+ * ### Format-Specific Implementation:
36
+ *
37
+ * Each processor should implement:
38
+ * - `extractSymbolsForLLM()` - Uses extractAllButtonsForTranslation() utility
39
+ * - `processLLMTranslations()` - Applies translations using format-specific logic
40
+ *
41
+ * See `src/utilities/translation/translationProcessor.ts` for shared utilities.
42
+ */
2
43
  Object.defineProperty(exports, "__esModule", { value: true });
3
44
  exports.BaseProcessor = void 0;
4
45
  const treeStructure_1 = require("./treeStructure");
@@ -29,6 +29,25 @@ export declare enum AACSemanticIntent {
29
29
  SCAN_SELECT = "SCAN_SELECT",
30
30
  PLATFORM_SPECIFIC = "PLATFORM_SPECIFIC"
31
31
  }
32
+ /**
33
+ * Scanning types for accessibility
34
+ */
35
+ export declare enum AACScanType {
36
+ LINEAR = "linear",// Left-to-right, top-to-bottom
37
+ ROW_COLUMN = "row-column",// Scan rows, then columns
38
+ COLUMN_ROW = "column-row",// Scan columns, then rows
39
+ BLOCK_ROW_COLUMN = "block-row-column",// Scan blocks, then rows, then columns
40
+ BLOCK_COLUMN_ROW = "block-column-row"
41
+ }
42
+ /**
43
+ * Configuration for a scan block
44
+ */
45
+ export interface AACScanBlock {
46
+ id: number;
47
+ name?: string;
48
+ order?: number;
49
+ scanType?: AACScanType;
50
+ }
32
51
  export interface AACSemanticAction {
33
52
  category?: AACSemanticCategory;
34
53
  intent: AACSemanticIntent | string;
@@ -110,7 +129,14 @@ export declare class AACButton implements IAACButton {
110
129
  y?: number;
111
130
  columnSpan?: number;
112
131
  rowSpan?: number;
132
+ /**
133
+ * @deprecated Use scanBlock instead (singular, not array)
134
+ */
113
135
  scanBlocks?: number[];
136
+ /**
137
+ * Scan block number (1-8) for block scanning
138
+ */
139
+ scanBlock?: number;
114
140
  visibility?: 'Visible' | 'Hidden' | 'Disabled' | 'PointerAndTouchOnly' | 'Empty';
115
141
  directActivate?: boolean;
116
142
  audioDescription?: string;
@@ -119,7 +145,7 @@ export declare class AACButton implements IAACButton {
119
145
  };
120
146
  semantic_id?: string;
121
147
  clone_id?: string;
122
- constructor({ id, label, message, targetPageId, semanticAction, audioRecording, style, contentType, contentSubType, image, resolvedImageEntry, symbolLibrary, symbolPath, x, y, columnSpan, rowSpan, scanBlocks, visibility, directActivate, parameters, semantic_id, clone_id, type, action, }: {
148
+ constructor({ id, label, message, targetPageId, semanticAction, audioRecording, style, contentType, contentSubType, image, resolvedImageEntry, symbolLibrary, symbolPath, x, y, columnSpan, rowSpan, scanBlocks, scanBlock, visibility, directActivate, parameters, semantic_id, clone_id, type, action, }: {
123
149
  id: string;
124
150
  label?: string;
125
151
  message?: string;
@@ -143,6 +169,7 @@ export declare class AACButton implements IAACButton {
143
169
  columnSpan?: number;
144
170
  rowSpan?: number;
145
171
  scanBlocks?: number[];
172
+ scanBlock?: number;
146
173
  visibility?: 'Visible' | 'Hidden' | 'Disabled' | 'PointerAndTouchOnly' | 'Empty';
147
174
  directActivate?: boolean;
148
175
  parameters?: {
@@ -177,7 +204,10 @@ export declare class AACPage implements IAACPage {
177
204
  sounds?: any[];
178
205
  semantic_ids?: string[];
179
206
  clone_ids?: string[];
180
- constructor({ id, name, grid, buttons, parentId, style, locale, descriptionHtml, images, sounds, semantic_ids, clone_ids, }: {
207
+ scanningConfig?: import('../types/aac').ScanningConfig;
208
+ scanType?: AACScanType;
209
+ scanBlocksConfig?: AACScanBlock[];
210
+ constructor({ id, name, grid, buttons, parentId, style, locale, descriptionHtml, images, sounds, semantic_ids, clone_ids, scanningConfig, scanBlocksConfig, scanType, }: {
181
211
  id: string;
182
212
  name?: string;
183
213
  grid?: Array<Array<AACButton | null>> | {
@@ -193,6 +223,9 @@ export declare class AACPage implements IAACPage {
193
223
  sounds?: any[];
194
224
  semantic_ids?: string[];
195
225
  clone_ids?: string[];
226
+ scanningConfig?: import('../types/aac').ScanningConfig;
227
+ scanBlocksConfig?: AACScanBlock[];
228
+ scanType?: AACScanType;
196
229
  });
197
230
  addButton(button: AACButton): void;
198
231
  }
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.AACTree = exports.AACPage = exports.AACButton = exports.AACSemanticIntent = exports.AACSemanticCategory = void 0;
3
+ exports.AACTree = exports.AACPage = exports.AACButton = exports.AACScanType = exports.AACSemanticIntent = exports.AACSemanticCategory = void 0;
4
4
  // Semantic action categories for cross-platform compatibility
5
5
  var AACSemanticCategory;
6
6
  (function (AACSemanticCategory) {
@@ -42,8 +42,19 @@ var AACSemanticIntent;
42
42
  // Custom
43
43
  AACSemanticIntent["PLATFORM_SPECIFIC"] = "PLATFORM_SPECIFIC";
44
44
  })(AACSemanticIntent || (exports.AACSemanticIntent = AACSemanticIntent = {}));
45
+ /**
46
+ * Scanning types for accessibility
47
+ */
48
+ var AACScanType;
49
+ (function (AACScanType) {
50
+ AACScanType["LINEAR"] = "linear";
51
+ AACScanType["ROW_COLUMN"] = "row-column";
52
+ AACScanType["COLUMN_ROW"] = "column-row";
53
+ AACScanType["BLOCK_ROW_COLUMN"] = "block-row-column";
54
+ AACScanType["BLOCK_COLUMN_ROW"] = "block-column-row";
55
+ })(AACScanType || (exports.AACScanType = AACScanType = {}));
45
56
  class AACButton {
46
- constructor({ id, label = '', message = '', targetPageId, semanticAction, audioRecording, style, contentType, contentSubType, image, resolvedImageEntry, symbolLibrary, symbolPath, x, y, columnSpan, rowSpan, scanBlocks, visibility, directActivate, parameters, semantic_id, clone_id,
57
+ constructor({ id, label = '', message = '', targetPageId, semanticAction, audioRecording, style, contentType, contentSubType, image, resolvedImageEntry, symbolLibrary, symbolPath, x, y, columnSpan, rowSpan, scanBlocks, scanBlock, visibility, directActivate, parameters, semantic_id, clone_id,
47
58
  // Legacy input support
48
59
  type, action, }) {
49
60
  this.id = id;
@@ -64,6 +75,7 @@ class AACButton {
64
75
  this.columnSpan = columnSpan;
65
76
  this.rowSpan = rowSpan;
66
77
  this.scanBlocks = scanBlocks;
78
+ this.scanBlock = scanBlock;
67
79
  this.visibility = visibility;
68
80
  this.directActivate = directActivate;
69
81
  this.parameters = parameters;
@@ -156,7 +168,7 @@ class AACButton {
156
168
  }
157
169
  exports.AACButton = AACButton;
158
170
  class AACPage {
159
- constructor({ id, name = '', grid = [], buttons = [], parentId = null, style, locale, descriptionHtml, images, sounds, semantic_ids, clone_ids, }) {
171
+ constructor({ id, name = '', grid = [], buttons = [], parentId = null, style, locale, descriptionHtml, images, sounds, semantic_ids, clone_ids, scanningConfig, scanBlocksConfig, scanType, }) {
160
172
  this.id = id;
161
173
  this.name = name;
162
174
  if (Array.isArray(grid)) {
@@ -179,6 +191,9 @@ class AACPage {
179
191
  this.sounds = sounds;
180
192
  this.semantic_ids = semantic_ids;
181
193
  this.clone_ids = clone_ids;
194
+ this.scanningConfig = scanningConfig;
195
+ this.scanBlocksConfig = scanBlocksConfig;
196
+ this.scanType = scanType;
182
197
  }
183
198
  addButton(button) {
184
199
  this.buttons.push(button);
package/dist/index.d.ts CHANGED
@@ -3,8 +3,8 @@ export * from './core/baseProcessor';
3
3
  export * from './core/stringCasing';
4
4
  export * from './processors';
5
5
  export * from './validation';
6
- export * as Analytics from './optional/analytics';
7
- export { collectUnifiedHistory, listGrid3Users as listHistoryGrid3Users, listSnapUsers as listHistorySnapUsers, } from './optional/analytics/history';
6
+ export * as Analytics from './utilities/analytics';
7
+ export { collectUnifiedHistory, listGrid3Users as listHistoryGrid3Users, listSnapUsers as listHistorySnapUsers, } from './utilities/analytics/history';
8
8
  import { BaseProcessor } from './core/baseProcessor';
9
9
  /**
10
10
  * Factory function to get the appropriate processor for a file extension
package/dist/index.js CHANGED
@@ -36,8 +36,8 @@ __exportStar(require("./core/baseProcessor"), exports);
36
36
  __exportStar(require("./core/stringCasing"), exports);
37
37
  __exportStar(require("./processors"), exports);
38
38
  __exportStar(require("./validation"), exports);
39
- exports.Analytics = __importStar(require("./optional/analytics"));
40
- var history_1 = require("./optional/analytics/history");
39
+ exports.Analytics = __importStar(require("./utilities/analytics"));
40
+ var history_1 = require("./utilities/analytics/history");
41
41
  Object.defineProperty(exports, "collectUnifiedHistory", { enumerable: true, get: function () { return history_1.collectUnifiedHistory; } });
42
42
  Object.defineProperty(exports, "listHistoryGrid3Users", { enumerable: true, get: function () { return history_1.listGrid3Users; } });
43
43
  Object.defineProperty(exports, "listHistorySnapUsers", { enumerable: true, get: function () { return history_1.listSnapUsers; } });
@@ -1,5 +1,20 @@
1
1
  import { BaseProcessor, ProcessorOptions, ExtractStringsResult, TranslatedString, SourceString } from '../core/baseProcessor';
2
2
  import { AACTree } from '../core/treeStructure';
3
+ export declare function normalizeHexColor(hexColor: string): string | null;
4
+ export declare function adjustHexColor(hexColor: string, amount: number): string;
5
+ export declare function getHighContrastNeutralColor(backgroundColor: string): string;
6
+ /**
7
+ * Calculate relative luminance of a color using WCAG formula
8
+ * @param hexColor - Hex color string (e.g., "#1d90ff")
9
+ * @returns Relative luminance value between 0 and 1
10
+ */
11
+ export declare function calculateLuminance(hexColor: string): number;
12
+ /**
13
+ * Choose white or black text color based on background luminance for optimal contrast
14
+ * @param backgroundColor - Background color hex string
15
+ * @returns "#FFFFFF" for dark backgrounds, "#000000" for light backgrounds
16
+ */
17
+ export declare function getContrastingTextColor(backgroundColor: string): string;
3
18
  declare class AstericsGridProcessor extends BaseProcessor {
4
19
  private loadAudio;
5
20
  constructor(options?: ProcessorOptions & {
@@ -4,6 +4,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.AstericsGridProcessor = void 0;
7
+ exports.normalizeHexColor = normalizeHexColor;
8
+ exports.adjustHexColor = adjustHexColor;
9
+ exports.getHighContrastNeutralColor = getHighContrastNeutralColor;
10
+ exports.calculateLuminance = calculateLuminance;
11
+ exports.getContrastingTextColor = getContrastingTextColor;
7
12
  const baseProcessor_1 = require("../core/baseProcessor");
8
13
  const treeStructure_1 = require("../core/treeStructure");
9
14
  const fs_1 = __importDefault(require("fs"));
@@ -535,6 +540,17 @@ function getContrastingTextColor(backgroundColor) {
535
540
  // WCAG threshold: use white text if luminance < 0.5, black otherwise
536
541
  return luminance < 0.5 ? '#FFFFFF' : '#000000';
537
542
  }
543
+ /**
544
+ * Map Asterics Grid hidden value to AAC standard visibility
545
+ * Asterics Grid: true = hidden, false = visible
546
+ * Maps to: 'Hidden' | 'Visible' | undefined
547
+ */
548
+ function mapAstericsVisibility(hidden) {
549
+ if (hidden === undefined) {
550
+ return undefined; // Default to visible
551
+ }
552
+ return hidden ? 'Hidden' : 'Visible';
553
+ }
538
554
  class AstericsGridProcessor extends baseProcessor_1.BaseProcessor {
539
555
  constructor(options = {}) {
540
556
  super(options);
@@ -979,6 +995,7 @@ class AstericsGridProcessor extends baseProcessor_1.BaseProcessor {
979
995
  targetPageId: targetPageId || undefined,
980
996
  semanticAction: semanticAction,
981
997
  audioRecording: audioRecording,
998
+ visibility: mapAstericsVisibility(element.hidden),
982
999
  image: imageName, // Store image filename/reference
983
1000
  parameters: imageData
984
1001
  ? {
@@ -1,4 +1,4 @@
1
- import { AACTree } from '../../core/treeStructure';
1
+ import { AACTree, AACSemanticCategory, AACSemanticIntent } from '../../core/treeStructure';
2
2
  /**
3
3
  * Build a map of button IDs to resolved image entry paths for a specific page.
4
4
  * Helpful when rewriting zip entry names or validating images referenced in a grid.
@@ -66,6 +66,9 @@ export interface Grid3HistoryEntry {
66
66
  timestamp: Date;
67
67
  latitude?: number | null;
68
68
  longitude?: number | null;
69
+ type?: 'button' | 'action' | 'utterance' | 'note' | 'other';
70
+ intent?: AACSemanticIntent | string;
71
+ category?: AACSemanticCategory;
69
72
  }>;
70
73
  rawXml?: string;
71
74
  }
@@ -44,6 +44,7 @@ exports.readGrid3HistoryForUser = readGrid3HistoryForUser;
44
44
  exports.readAllGrid3History = readAllGrid3History;
45
45
  const adm_zip_1 = __importDefault(require("adm-zip"));
46
46
  const fast_xml_parser_1 = require("fast-xml-parser");
47
+ const treeStructure_1 = require("../../core/treeStructure");
47
48
  const fs = __importStar(require("fs"));
48
49
  const path = __importStar(require("path"));
49
50
  const child_process_1 = require("child_process");
@@ -394,6 +395,9 @@ function readGrid3History(historyDbPath) {
394
395
  timestamp: (0, dotnetTicks_1.dotNetTicksToDate)(BigInt(row.TickValue ?? 0)),
395
396
  latitude: row.Latitude ?? null,
396
397
  longitude: row.Longitude ?? null,
398
+ type: 'utterance',
399
+ intent: treeStructure_1.AACSemanticIntent.SPEAK_TEXT,
400
+ category: treeStructure_1.AACSemanticCategory.COMMUNICATION,
397
401
  });
398
402
  events.set(phraseId, entry);
399
403
  }