@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
@@ -0,0 +1,37 @@
1
+ /**
2
+ * String casing utilities for AAC text processing
3
+ * Used for detecting and managing text casing across different AAC formats
4
+ */
5
+ export declare enum StringCasing {
6
+ LOWER = "lower",
7
+ SNAKE = "snake",
8
+ CONSTANT = "constant",
9
+ CAMEL = "camel",
10
+ UPPER = "upper",
11
+ KEBAB = "kebab",
12
+ CAPITAL = "capital",
13
+ HEADER = "header",
14
+ PASCAL = "pascal",
15
+ TITLE = "title",
16
+ SENTENCE = "sentence"
17
+ }
18
+ /**
19
+ * Detects the casing pattern of a given text string
20
+ * @param text - The text to analyze for casing pattern
21
+ * @returns StringCasing enum value representing the detected casing
22
+ */
23
+ export declare function detectCasing(text: string): StringCasing;
24
+ /**
25
+ * Converts text to the specified casing
26
+ * @param text - The text to convert
27
+ * @param targetCasing - The desired casing format
28
+ * @returns The text converted to the target casing
29
+ */
30
+ export declare function convertCasing(text: string, targetCasing: StringCasing): string;
31
+ /**
32
+ * Utility function to check if text is primarily numeric or empty
33
+ * Used for filtering out non-meaningful text content
34
+ * @param text - The text to check
35
+ * @returns True if the text should be considered non-meaningful
36
+ */
37
+ export declare function isNumericOrEmpty(text: string): boolean;
@@ -0,0 +1,174 @@
1
+ "use strict";
2
+ /**
3
+ * String casing utilities for AAC text processing
4
+ * Used for detecting and managing text casing across different AAC formats
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.StringCasing = void 0;
8
+ exports.detectCasing = detectCasing;
9
+ exports.convertCasing = convertCasing;
10
+ exports.isNumericOrEmpty = isNumericOrEmpty;
11
+ var StringCasing;
12
+ (function (StringCasing) {
13
+ StringCasing["LOWER"] = "lower";
14
+ StringCasing["SNAKE"] = "snake";
15
+ StringCasing["CONSTANT"] = "constant";
16
+ StringCasing["CAMEL"] = "camel";
17
+ StringCasing["UPPER"] = "upper";
18
+ StringCasing["KEBAB"] = "kebab";
19
+ StringCasing["CAPITAL"] = "capital";
20
+ StringCasing["HEADER"] = "header";
21
+ StringCasing["PASCAL"] = "pascal";
22
+ StringCasing["TITLE"] = "title";
23
+ StringCasing["SENTENCE"] = "sentence";
24
+ })(StringCasing || (exports.StringCasing = StringCasing = {}));
25
+ /**
26
+ * Detects the casing pattern of a given text string
27
+ * @param text - The text to analyze for casing pattern
28
+ * @returns StringCasing enum value representing the detected casing
29
+ */
30
+ function detectCasing(text) {
31
+ if (!text || text.length === 0)
32
+ return StringCasing.LOWER;
33
+ // Remove leading/trailing whitespace for analysis
34
+ const trimmed = text.trim();
35
+ if (trimmed.length === 0)
36
+ return StringCasing.LOWER;
37
+ // Check for specific patterns
38
+ // CONSTANT_CASE (ALL_CAPS_WITH_UNDERSCORES)
39
+ if (/^[A-Z][A-Z0-9_]*$/.test(trimmed) && trimmed.includes('_')) {
40
+ return StringCasing.CONSTANT;
41
+ }
42
+ // snake_case (lowercase_with_underscores)
43
+ if (/^[a-z][a-z0-9_]*$/.test(trimmed) && trimmed.includes('_')) {
44
+ return StringCasing.SNAKE;
45
+ }
46
+ // kebab-case (lowercase-with-hyphens)
47
+ if (/^[a-z][a-z0-9-]*$/.test(trimmed) && trimmed.includes('-')) {
48
+ return StringCasing.KEBAB;
49
+ }
50
+ // camelCase (firstWordLowerCaseFollowingWordsCapitalized)
51
+ if (/^[a-z][a-zA-Z0-9]*$/.test(trimmed) && /[A-Z]/.test(trimmed)) {
52
+ return StringCasing.CAMEL;
53
+ }
54
+ // PascalCase (FirstWordAndFollowingWordsCapitalized)
55
+ if (/^[A-Z][a-zA-Z0-9]*$/.test(trimmed) &&
56
+ /[a-z]/.test(trimmed) &&
57
+ /[A-Z].*[A-Z]/.test(trimmed)) {
58
+ return StringCasing.PASCAL;
59
+ }
60
+ // UPPER CASE (ALL UPPERCASE) - but only if more than one character
61
+ if (trimmed === trimmed.toUpperCase() && /[A-Z]/.test(trimmed) && trimmed.length > 1) {
62
+ return StringCasing.UPPER;
63
+ }
64
+ // lower case (all lowercase)
65
+ if (trimmed === trimmed.toLowerCase() && /[a-z]/.test(trimmed)) {
66
+ return StringCasing.LOWER;
67
+ }
68
+ // Title Case (First Letter Of Each Word Capitalized)
69
+ const words = trimmed.split(/\s+/);
70
+ if (words.length > 1 &&
71
+ words.every((word) => word.length > 0 &&
72
+ word[0] === word[0].toUpperCase() &&
73
+ (word.length === 1 || word.slice(1) === word.slice(1).toLowerCase()))) {
74
+ return StringCasing.TITLE;
75
+ }
76
+ // Header-Case (First-Letter-Of-Each-Word-Capitalized-With-Hyphens)
77
+ if (trimmed.includes('-')) {
78
+ const hyphenWords = trimmed.split('-');
79
+ if (hyphenWords.length > 1 &&
80
+ hyphenWords.every((word) => word.length > 0 &&
81
+ word[0] === word[0].toUpperCase() &&
82
+ (word.length === 1 || word.slice(1) === word.slice(1).toLowerCase()))) {
83
+ return StringCasing.HEADER;
84
+ }
85
+ }
86
+ // Sentence case (First letter capitalized, rest lowercase)
87
+ if (trimmed.length > 1 &&
88
+ trimmed[0] === trimmed[0].toUpperCase() &&
89
+ trimmed.slice(1) === trimmed.slice(1).toLowerCase()) {
90
+ return StringCasing.SENTENCE;
91
+ }
92
+ // Capital case (Just first letter capitalized, may have mixed case after)
93
+ if (trimmed[0] === trimmed[0].toUpperCase()) {
94
+ return StringCasing.CAPITAL;
95
+ }
96
+ // Default fallback
97
+ return StringCasing.LOWER;
98
+ }
99
+ /**
100
+ * Converts text to the specified casing
101
+ * @param text - The text to convert
102
+ * @param targetCasing - The desired casing format
103
+ * @returns The text converted to the target casing
104
+ */
105
+ function convertCasing(text, targetCasing) {
106
+ if (!text || text.length === 0)
107
+ return text;
108
+ const trimmed = text.trim();
109
+ if (trimmed.length === 0)
110
+ return text;
111
+ switch (targetCasing) {
112
+ case StringCasing.LOWER:
113
+ return trimmed.toLowerCase();
114
+ case StringCasing.UPPER:
115
+ return trimmed.toUpperCase();
116
+ case StringCasing.CAPITAL:
117
+ return trimmed.charAt(0).toUpperCase() + trimmed.slice(1).toLowerCase();
118
+ case StringCasing.SENTENCE:
119
+ return trimmed.charAt(0).toUpperCase() + trimmed.slice(1).toLowerCase();
120
+ case StringCasing.TITLE:
121
+ return trimmed
122
+ .split(/\s+/)
123
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
124
+ .join(' ');
125
+ case StringCasing.CAMEL:
126
+ return trimmed
127
+ .split(/[\s_-]+/)
128
+ .map((word, index) => index === 0
129
+ ? word.toLowerCase()
130
+ : word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
131
+ .join('');
132
+ case StringCasing.PASCAL:
133
+ return trimmed
134
+ .split(/[\s_-]+/)
135
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
136
+ .join('');
137
+ case StringCasing.SNAKE:
138
+ return trimmed
139
+ .split(/[\s-]+/)
140
+ .map((word) => word.toLowerCase())
141
+ .join('_');
142
+ case StringCasing.CONSTANT:
143
+ return trimmed
144
+ .split(/[\s-]+/)
145
+ .map((word) => word.toUpperCase())
146
+ .join('_');
147
+ case StringCasing.KEBAB:
148
+ return trimmed
149
+ .split(/[\s_]+/)
150
+ .map((word) => word.toLowerCase())
151
+ .join('-');
152
+ case StringCasing.HEADER:
153
+ return trimmed
154
+ .split(/[\s_]+/)
155
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
156
+ .join('-');
157
+ default:
158
+ return trimmed;
159
+ }
160
+ }
161
+ /**
162
+ * Utility function to check if text is primarily numeric or empty
163
+ * Used for filtering out non-meaningful text content
164
+ * @param text - The text to check
165
+ * @returns True if the text should be considered non-meaningful
166
+ */
167
+ function isNumericOrEmpty(text) {
168
+ const trimmed = text.trim();
169
+ if (trimmed.length <= 1)
170
+ return true;
171
+ // Check if the entire string is numeric
172
+ const numericValue = parseInt(trimmed, 10);
173
+ return !isNaN(numericValue) && numericValue.toString() === trimmed;
174
+ }
@@ -0,0 +1,190 @@
1
+ import { AACButton as IAACButton, AACPage as IAACPage, AACTree as IAACTree, AACStyle } from '../types/aac';
2
+ export declare enum AACSemanticCategory {
3
+ COMMUNICATION = "communication",// Speech, text output
4
+ NAVIGATION = "navigation",// Page/grid navigation
5
+ TEXT_EDITING = "text_editing",// Text manipulation
6
+ SYSTEM_CONTROL = "system_control",// Device/app control
7
+ MEDIA = "media",// Audio/video playback
8
+ ACCESSIBILITY = "accessibility",// Switch scanning, etc.
9
+ CUSTOM = "custom"
10
+ }
11
+ export declare enum AACSemanticIntent {
12
+ SPEAK_TEXT = "SPEAK_TEXT",
13
+ SPEAK_IMMEDIATE = "SPEAK_IMMEDIATE",
14
+ STOP_SPEECH = "STOP_SPEECH",
15
+ INSERT_TEXT = "INSERT_TEXT",
16
+ NAVIGATE_TO = "NAVIGATE_TO",
17
+ GO_BACK = "GO_BACK",
18
+ GO_HOME = "GO_HOME",
19
+ DELETE_WORD = "DELETE_WORD",
20
+ DELETE_CHARACTER = "DELETE_CHARACTER",
21
+ CLEAR_TEXT = "CLEAR_TEXT",
22
+ COPY_TEXT = "COPY_TEXT",
23
+ PASTE_TEXT = "PASTE_TEXT",
24
+ SEND_KEYS = "SEND_KEYS",
25
+ MOUSE_CLICK = "MOUSE_CLICK",
26
+ PLAY_SOUND = "PLAY_SOUND",
27
+ PLAY_VIDEO = "PLAY_VIDEO",
28
+ SCAN_NEXT = "SCAN_NEXT",
29
+ SCAN_SELECT = "SCAN_SELECT",
30
+ PLATFORM_SPECIFIC = "PLATFORM_SPECIFIC"
31
+ }
32
+ export interface AACSemanticAction {
33
+ category?: AACSemanticCategory;
34
+ intent: AACSemanticIntent | string;
35
+ text?: string;
36
+ targetId?: string;
37
+ audioData?: Buffer;
38
+ richText?: {
39
+ text: string;
40
+ symbols?: Array<{
41
+ text: string;
42
+ image?: string;
43
+ }>;
44
+ grammar?: {
45
+ partOfSpeech?: string;
46
+ person?: string;
47
+ number?: string;
48
+ verbState?: string;
49
+ };
50
+ };
51
+ parameters?: {
52
+ [key: string]: any;
53
+ };
54
+ platformData?: {
55
+ grid3?: {
56
+ commandId: string;
57
+ parameters: {
58
+ [key: string]: any;
59
+ };
60
+ };
61
+ astericsGrid?: {
62
+ modelName: string;
63
+ properties: {
64
+ [key: string]: any;
65
+ };
66
+ };
67
+ touchChat?: {
68
+ actionCode: number;
69
+ actionData: string;
70
+ };
71
+ snap?: {
72
+ navigatePageId?: number;
73
+ elementReferenceId?: number;
74
+ };
75
+ applePanels?: {
76
+ actionType: string;
77
+ parameters: {
78
+ [key: string]: any;
79
+ };
80
+ };
81
+ };
82
+ fallback?: {
83
+ type: 'SPEAK' | 'NAVIGATE' | 'ACTION';
84
+ message?: string;
85
+ targetPageId?: string;
86
+ };
87
+ }
88
+ export declare class AACButton implements IAACButton {
89
+ id: string;
90
+ label: string;
91
+ message: string;
92
+ semanticAction?: AACSemanticAction;
93
+ targetPageId?: string;
94
+ style?: AACStyle;
95
+ audioRecording?: {
96
+ id?: number;
97
+ data?: Buffer;
98
+ identifier?: string;
99
+ metadata?: string;
100
+ };
101
+ contentType?: 'Normal' | 'AutoContent' | 'Workspace' | 'LiveCell';
102
+ contentSubType?: string;
103
+ image?: string;
104
+ resolvedImageEntry?: string;
105
+ symbolLibrary?: string;
106
+ symbolPath?: string;
107
+ x?: number;
108
+ y?: number;
109
+ columnSpan?: number;
110
+ rowSpan?: number;
111
+ scanBlocks?: number[];
112
+ visibility?: 'Visible' | 'Hidden' | 'Disabled' | 'PointerAndTouchOnly' | 'Empty';
113
+ directActivate?: boolean;
114
+ audioDescription?: string;
115
+ parameters?: {
116
+ [key: string]: any;
117
+ };
118
+ constructor({ id, label, message, targetPageId, semanticAction, audioRecording, style, contentType, contentSubType, image, resolvedImageEntry, x, y, columnSpan, rowSpan, scanBlocks, visibility, directActivate, parameters, type, action, }: {
119
+ id: string;
120
+ label?: string;
121
+ message?: string;
122
+ targetPageId?: string;
123
+ semanticAction?: AACSemanticAction;
124
+ audioRecording?: {
125
+ id?: number;
126
+ data?: Buffer;
127
+ identifier?: string;
128
+ metadata?: string;
129
+ };
130
+ style?: AACStyle;
131
+ contentType?: 'Normal' | 'AutoContent' | 'Workspace' | 'LiveCell';
132
+ contentSubType?: string;
133
+ image?: string;
134
+ resolvedImageEntry?: string;
135
+ x?: number;
136
+ y?: number;
137
+ columnSpan?: number;
138
+ rowSpan?: number;
139
+ scanBlocks?: number[];
140
+ visibility?: 'Visible' | 'Hidden' | 'Disabled' | 'PointerAndTouchOnly' | 'Empty';
141
+ directActivate?: boolean;
142
+ parameters?: {
143
+ [key: string]: any;
144
+ };
145
+ type?: 'SPEAK' | 'NAVIGATE' | 'ACTION';
146
+ action?: {
147
+ type: 'SPEAK' | 'NAVIGATE' | 'ACTION';
148
+ targetPageId?: string;
149
+ message?: string;
150
+ } | null;
151
+ });
152
+ get type(): 'SPEAK' | 'NAVIGATE' | 'ACTION' | undefined;
153
+ get action(): {
154
+ type: 'SPEAK' | 'NAVIGATE' | 'ACTION';
155
+ targetPageId?: string;
156
+ message?: string;
157
+ } | null;
158
+ }
159
+ export declare class AACPage implements IAACPage {
160
+ id: string;
161
+ name: string;
162
+ grid: Array<Array<AACButton | null>>;
163
+ buttons: AACButton[];
164
+ parentId: string | null;
165
+ style?: AACStyle;
166
+ constructor({ id, name, grid, buttons, parentId, style, }: {
167
+ id: string;
168
+ name?: string;
169
+ grid?: Array<Array<AACButton | null>> | {
170
+ columns: number;
171
+ rows: number;
172
+ };
173
+ buttons?: AACButton[];
174
+ parentId?: string | null;
175
+ style?: AACStyle;
176
+ });
177
+ addButton(button: AACButton): void;
178
+ }
179
+ export declare class AACTree implements IAACTree {
180
+ pages: {
181
+ [key: string]: AACPage;
182
+ };
183
+ private _rootId;
184
+ get rootId(): string | null;
185
+ set rootId(id: string | null);
186
+ constructor();
187
+ addPage(page: AACPage): void;
188
+ getPage(id: string): AACPage | undefined;
189
+ traverse(callback: (page: AACPage) => void): void;
190
+ }
@@ -0,0 +1,223 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AACTree = exports.AACPage = exports.AACButton = exports.AACSemanticIntent = exports.AACSemanticCategory = void 0;
4
+ // Semantic action categories for cross-platform compatibility
5
+ var AACSemanticCategory;
6
+ (function (AACSemanticCategory) {
7
+ AACSemanticCategory["COMMUNICATION"] = "communication";
8
+ AACSemanticCategory["NAVIGATION"] = "navigation";
9
+ AACSemanticCategory["TEXT_EDITING"] = "text_editing";
10
+ AACSemanticCategory["SYSTEM_CONTROL"] = "system_control";
11
+ AACSemanticCategory["MEDIA"] = "media";
12
+ AACSemanticCategory["ACCESSIBILITY"] = "accessibility";
13
+ AACSemanticCategory["CUSTOM"] = "custom";
14
+ })(AACSemanticCategory || (exports.AACSemanticCategory = AACSemanticCategory = {}));
15
+ // Semantic intents within each category
16
+ var AACSemanticIntent;
17
+ (function (AACSemanticIntent) {
18
+ // Communication
19
+ AACSemanticIntent["SPEAK_TEXT"] = "SPEAK_TEXT";
20
+ AACSemanticIntent["SPEAK_IMMEDIATE"] = "SPEAK_IMMEDIATE";
21
+ AACSemanticIntent["STOP_SPEECH"] = "STOP_SPEECH";
22
+ AACSemanticIntent["INSERT_TEXT"] = "INSERT_TEXT";
23
+ // Navigation
24
+ AACSemanticIntent["NAVIGATE_TO"] = "NAVIGATE_TO";
25
+ AACSemanticIntent["GO_BACK"] = "GO_BACK";
26
+ AACSemanticIntent["GO_HOME"] = "GO_HOME";
27
+ // Text Editing
28
+ AACSemanticIntent["DELETE_WORD"] = "DELETE_WORD";
29
+ AACSemanticIntent["DELETE_CHARACTER"] = "DELETE_CHARACTER";
30
+ AACSemanticIntent["CLEAR_TEXT"] = "CLEAR_TEXT";
31
+ AACSemanticIntent["COPY_TEXT"] = "COPY_TEXT";
32
+ AACSemanticIntent["PASTE_TEXT"] = "PASTE_TEXT";
33
+ // System Control
34
+ AACSemanticIntent["SEND_KEYS"] = "SEND_KEYS";
35
+ AACSemanticIntent["MOUSE_CLICK"] = "MOUSE_CLICK";
36
+ // Media
37
+ AACSemanticIntent["PLAY_SOUND"] = "PLAY_SOUND";
38
+ AACSemanticIntent["PLAY_VIDEO"] = "PLAY_VIDEO";
39
+ // Accessibility
40
+ AACSemanticIntent["SCAN_NEXT"] = "SCAN_NEXT";
41
+ AACSemanticIntent["SCAN_SELECT"] = "SCAN_SELECT";
42
+ // Custom
43
+ AACSemanticIntent["PLATFORM_SPECIFIC"] = "PLATFORM_SPECIFIC";
44
+ })(AACSemanticIntent || (exports.AACSemanticIntent = AACSemanticIntent = {}));
45
+ class AACButton {
46
+ constructor({ id, label = '', message = '', targetPageId, semanticAction, audioRecording, style, contentType, contentSubType, image, resolvedImageEntry, x, y, columnSpan, rowSpan, scanBlocks, visibility, directActivate, parameters,
47
+ // Legacy input support
48
+ type, action, }) {
49
+ this.id = id;
50
+ this.label = label;
51
+ this.message = message;
52
+ this.targetPageId = targetPageId;
53
+ this.semanticAction = semanticAction;
54
+ this.audioRecording = audioRecording;
55
+ this.style = style;
56
+ this.contentType = contentType;
57
+ this.contentSubType = contentSubType;
58
+ this.image = image;
59
+ this.resolvedImageEntry = resolvedImageEntry;
60
+ this.x = x;
61
+ this.y = y;
62
+ this.columnSpan = columnSpan;
63
+ this.rowSpan = rowSpan;
64
+ this.scanBlocks = scanBlocks;
65
+ this.visibility = visibility;
66
+ this.directActivate = directActivate;
67
+ this.parameters = parameters;
68
+ // Legacy mapping: if no semanticAction provided, derive from legacy `action` first
69
+ if (!this.semanticAction && action) {
70
+ if (action.type === 'NAVIGATE' && (action.targetPageId || this.targetPageId)) {
71
+ if (!this.targetPageId)
72
+ this.targetPageId = action.targetPageId;
73
+ this.semanticAction = {
74
+ category: AACSemanticCategory.NAVIGATION,
75
+ intent: AACSemanticIntent.NAVIGATE_TO,
76
+ targetId: this.targetPageId,
77
+ fallback: { type: 'NAVIGATE', targetPageId: this.targetPageId },
78
+ };
79
+ }
80
+ else if (action.type === 'SPEAK') {
81
+ const text = action.message || this.message || this.label || '';
82
+ if (!this.message)
83
+ this.message = text;
84
+ this.semanticAction = {
85
+ category: AACSemanticCategory.COMMUNICATION,
86
+ intent: AACSemanticIntent.SPEAK_TEXT,
87
+ text,
88
+ fallback: { type: 'SPEAK', message: text },
89
+ };
90
+ }
91
+ else {
92
+ this.semanticAction = {
93
+ category: AACSemanticCategory.SYSTEM_CONTROL,
94
+ intent: AACSemanticIntent.PLATFORM_SPECIFIC,
95
+ fallback: { type: 'ACTION' },
96
+ };
97
+ }
98
+ }
99
+ // Legacy mapping: if still no semanticAction and `type` provided
100
+ if (!this.semanticAction && type) {
101
+ if (type === 'NAVIGATE' && this.targetPageId) {
102
+ this.semanticAction = {
103
+ category: AACSemanticCategory.NAVIGATION,
104
+ intent: AACSemanticIntent.NAVIGATE_TO,
105
+ targetId: this.targetPageId,
106
+ fallback: { type: 'NAVIGATE', targetPageId: this.targetPageId },
107
+ };
108
+ }
109
+ else if (type === 'SPEAK') {
110
+ const text = this.message || this.label || '';
111
+ this.semanticAction = {
112
+ category: AACSemanticCategory.COMMUNICATION,
113
+ intent: AACSemanticIntent.SPEAK_TEXT,
114
+ text,
115
+ fallback: { type: 'SPEAK', message: text },
116
+ };
117
+ }
118
+ else {
119
+ this.semanticAction = {
120
+ category: AACSemanticCategory.SYSTEM_CONTROL,
121
+ intent: AACSemanticIntent.PLATFORM_SPECIFIC,
122
+ fallback: { type: 'ACTION' },
123
+ };
124
+ }
125
+ }
126
+ }
127
+ // Legacy compatibility properties
128
+ get type() {
129
+ if (this.semanticAction) {
130
+ const i = String(this.semanticAction.intent);
131
+ if (i === 'NAVIGATE_TO')
132
+ return 'NAVIGATE';
133
+ if (i === 'SPEAK_TEXT' || i === 'SPEAK_IMMEDIATE')
134
+ return 'SPEAK';
135
+ return 'ACTION';
136
+ }
137
+ if (this.targetPageId)
138
+ return 'NAVIGATE';
139
+ if (this.message)
140
+ return 'SPEAK';
141
+ return 'SPEAK';
142
+ }
143
+ get action() {
144
+ const t = this.type;
145
+ if (!t)
146
+ return null;
147
+ if (t === 'SPEAK' && !this.message && !this.label && !this.semanticAction) {
148
+ return null;
149
+ }
150
+ return { type: t, targetPageId: this.targetPageId, message: this.message };
151
+ }
152
+ }
153
+ exports.AACButton = AACButton;
154
+ class AACPage {
155
+ constructor({ id, name = '', grid = [], buttons = [], parentId = null, style, }) {
156
+ this.id = id;
157
+ this.name = name;
158
+ if (Array.isArray(grid)) {
159
+ this.grid = grid;
160
+ }
161
+ else if (grid && typeof grid === 'object' && 'columns' in grid && 'rows' in grid) {
162
+ const cols = grid.columns;
163
+ const rows = grid.rows;
164
+ this.grid = Array.from({ length: rows }, () => Array.from({ length: cols }, () => null));
165
+ }
166
+ else {
167
+ this.grid = [];
168
+ }
169
+ this.buttons = buttons;
170
+ this.parentId = parentId;
171
+ this.style = style;
172
+ }
173
+ addButton(button) {
174
+ this.buttons.push(button);
175
+ }
176
+ }
177
+ exports.AACPage = AACPage;
178
+ class AACTree {
179
+ get rootId() {
180
+ return this._rootId;
181
+ }
182
+ set rootId(id) {
183
+ this._rootId = id;
184
+ }
185
+ constructor() {
186
+ this.pages = {};
187
+ this._rootId = null;
188
+ }
189
+ addPage(page) {
190
+ this.pages[page.id] = page;
191
+ if (!this._rootId)
192
+ this._rootId = page.id;
193
+ }
194
+ getPage(id) {
195
+ return this.pages[id];
196
+ }
197
+ traverse(callback) {
198
+ const queue = Object.keys(this.pages);
199
+ const visited = new Set();
200
+ while (queue.length > 0) {
201
+ const id = queue.shift();
202
+ if (!id || visited.has(id))
203
+ continue;
204
+ visited.add(id);
205
+ const page = this.pages[id];
206
+ if (page) {
207
+ callback(page);
208
+ // Add child pages to queue
209
+ page.buttons
210
+ .filter((b) => {
211
+ const i = String(b.semanticAction?.intent);
212
+ return i === 'NAVIGATE_TO' || !!b.semanticAction?.targetId || !!b.targetPageId;
213
+ })
214
+ .forEach((b) => {
215
+ const target = b.semanticAction?.targetId || b.targetPageId;
216
+ if (target)
217
+ queue.push(target);
218
+ });
219
+ }
220
+ }
221
+ }
222
+ }
223
+ exports.AACTree = AACTree;
@@ -0,0 +1,23 @@
1
+ export * from './core/treeStructure';
2
+ export * from './core/baseProcessor';
3
+ export * from './core/stringCasing';
4
+ export * from './processors';
5
+ import { BaseProcessor } from './core/baseProcessor';
6
+ /**
7
+ * Factory function to get the appropriate processor for a file extension
8
+ * @param filePathOrExtension - File path or extension (e.g., '.dot', '/path/to/file.obf')
9
+ * @returns The appropriate processor instance
10
+ * @throws Error if the file extension is not supported
11
+ */
12
+ export declare function getProcessor(filePathOrExtension: string): BaseProcessor;
13
+ /**
14
+ * Get all supported file extensions
15
+ * @returns Array of supported file extensions
16
+ */
17
+ export declare function getSupportedExtensions(): string[];
18
+ /**
19
+ * Check if a file extension is supported
20
+ * @param extension - File extension to check
21
+ * @returns True if the extension is supported
22
+ */
23
+ export declare function isExtensionSupported(extension: string): boolean;