@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.
- package/LICENSE +674 -0
- package/README.md +787 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +189 -0
- package/dist/cli/prettyPrint.d.ts +2 -0
- package/dist/cli/prettyPrint.js +28 -0
- package/dist/core/analyze.d.ts +6 -0
- package/dist/core/analyze.js +49 -0
- package/dist/core/baseProcessor.d.ts +94 -0
- package/dist/core/baseProcessor.js +208 -0
- package/dist/core/fileProcessor.d.ts +7 -0
- package/dist/core/fileProcessor.js +51 -0
- package/dist/core/stringCasing.d.ts +37 -0
- package/dist/core/stringCasing.js +174 -0
- package/dist/core/treeStructure.d.ts +190 -0
- package/dist/core/treeStructure.js +223 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +96 -0
- package/dist/optional/symbolTools.d.ts +28 -0
- package/dist/optional/symbolTools.js +126 -0
- package/dist/processors/applePanelsProcessor.d.ts +23 -0
- package/dist/processors/applePanelsProcessor.js +521 -0
- package/dist/processors/astericsGridProcessor.d.ts +49 -0
- package/dist/processors/astericsGridProcessor.js +1427 -0
- package/dist/processors/dotProcessor.d.ts +21 -0
- package/dist/processors/dotProcessor.js +191 -0
- package/dist/processors/excelProcessor.d.ts +145 -0
- package/dist/processors/excelProcessor.js +556 -0
- package/dist/processors/gridset/helpers.d.ts +4 -0
- package/dist/processors/gridset/helpers.js +48 -0
- package/dist/processors/gridset/resolver.d.ts +8 -0
- package/dist/processors/gridset/resolver.js +100 -0
- package/dist/processors/gridsetProcessor.d.ts +28 -0
- package/dist/processors/gridsetProcessor.js +1339 -0
- package/dist/processors/index.d.ts +14 -0
- package/dist/processors/index.js +42 -0
- package/dist/processors/obfProcessor.d.ts +21 -0
- package/dist/processors/obfProcessor.js +278 -0
- package/dist/processors/opmlProcessor.d.ts +21 -0
- package/dist/processors/opmlProcessor.js +235 -0
- package/dist/processors/snap/helpers.d.ts +4 -0
- package/dist/processors/snap/helpers.js +27 -0
- package/dist/processors/snapProcessor.d.ts +44 -0
- package/dist/processors/snapProcessor.js +586 -0
- package/dist/processors/touchchat/helpers.d.ts +4 -0
- package/dist/processors/touchchat/helpers.js +27 -0
- package/dist/processors/touchchatProcessor.d.ts +27 -0
- package/dist/processors/touchchatProcessor.js +768 -0
- package/dist/types/aac.d.ts +47 -0
- package/dist/types/aac.js +2 -0
- package/docs/.keep +1 -0
- package/docs/ApplePanels.md +309 -0
- package/docs/Grid3-XML-Format.md +1788 -0
- package/docs/TobiiDynavox-Snap-Details.md +394 -0
- package/docs/asterics-Grid-fileformat-details.md +443 -0
- package/docs/obf_.obz Open Board File Formats.md +432 -0
- package/docs/touchchat.md +520 -0
- package/examples/.coverage +0 -0
- package/examples/.keep +1 -0
- package/examples/README.md +31 -0
- package/examples/communikate.dot +2637 -0
- package/examples/demo.js +143 -0
- package/examples/example-images.gridset +0 -0
- package/examples/example.ce +0 -0
- package/examples/example.dot +14 -0
- package/examples/example.grd +1 -0
- package/examples/example.gridset +0 -0
- package/examples/example.obf +27 -0
- package/examples/example.obz +0 -0
- package/examples/example.opml +18 -0
- package/examples/example.spb +0 -0
- package/examples/example.sps +0 -0
- package/examples/example2.grd +1 -0
- package/examples/gemini_response.txt +845 -0
- package/examples/image-map.js +45 -0
- package/examples/package-lock.json +1326 -0
- package/examples/package.json +10 -0
- package/examples/styled-output/converted-snap-to-touchchat.ce +0 -0
- package/examples/styled-output/styled-example.ce +0 -0
- package/examples/styled-output/styled-example.gridset +0 -0
- package/examples/styled-output/styled-example.obf +37 -0
- package/examples/styled-output/styled-example.spb +0 -0
- package/examples/styling-example.ts +316 -0
- package/examples/translate.js +39 -0
- package/examples/translate_demo.js +254 -0
- package/examples/translation_cache.json +44894 -0
- package/examples/typescript-demo.ts +251 -0
- package/examples/unified-interface-demo.ts +183 -0
- 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;
|
package/dist/index.d.ts
ADDED
|
@@ -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;
|