@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,251 @@
|
|
|
1
|
+
#!/usr/bin/env ts-node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* TypeScript Demo - AACProcessors 2.0
|
|
5
|
+
*
|
|
6
|
+
* This example demonstrates the new TypeScript API and features
|
|
7
|
+
* including translation workflows and cross-format conversion.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
getProcessor,
|
|
12
|
+
DotProcessor,
|
|
13
|
+
ObfProcessor,
|
|
14
|
+
AACTree,
|
|
15
|
+
AACPage,
|
|
16
|
+
AACButton
|
|
17
|
+
} from '../src/index';
|
|
18
|
+
import fs from 'fs';
|
|
19
|
+
import path from 'path';
|
|
20
|
+
|
|
21
|
+
async function main() {
|
|
22
|
+
console.log('🚀 AACProcessors 2.0 TypeScript Demo\n');
|
|
23
|
+
|
|
24
|
+
// Example 1: Auto-detect processor by file extension
|
|
25
|
+
console.log('📁 Example 1: Auto-detection');
|
|
26
|
+
try {
|
|
27
|
+
const dotFile = path.join(__dirname, 'example.dot');
|
|
28
|
+
if (fs.existsSync(dotFile)) {
|
|
29
|
+
const processor = getProcessor(dotFile);
|
|
30
|
+
console.log(`✅ Detected processor: ${processor.constructor.name}`);
|
|
31
|
+
|
|
32
|
+
const tree = processor.loadIntoTree(dotFile);
|
|
33
|
+
console.log(`📊 Loaded ${Object.keys(tree.pages).length} pages`);
|
|
34
|
+
|
|
35
|
+
const texts = processor.extractTexts(dotFile);
|
|
36
|
+
console.log(`📝 Found ${texts.length} text elements`);
|
|
37
|
+
} else {
|
|
38
|
+
console.log('⚠️ example.dot not found, skipping auto-detection demo');
|
|
39
|
+
}
|
|
40
|
+
} catch (error) {
|
|
41
|
+
console.error('❌ Auto-detection error:', error);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
console.log('\n' + '='.repeat(50) + '\n');
|
|
45
|
+
|
|
46
|
+
// Example 2: Create a communication board programmatically
|
|
47
|
+
console.log('🏗️ Example 2: Programmatic Board Creation');
|
|
48
|
+
|
|
49
|
+
const tree = new AACTree();
|
|
50
|
+
|
|
51
|
+
// Create home page
|
|
52
|
+
const homePage = new AACPage({
|
|
53
|
+
id: 'home',
|
|
54
|
+
name: 'Home Page',
|
|
55
|
+
buttons: []
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// Add buttons
|
|
59
|
+
const greetingButton = new AACButton({
|
|
60
|
+
id: 'btn_hello',
|
|
61
|
+
label: 'Hello',
|
|
62
|
+
message: 'Hello, how are you today?',
|
|
63
|
+
type: 'SPEAK'
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const foodButton = new AACButton({
|
|
67
|
+
id: 'btn_food',
|
|
68
|
+
label: 'Food',
|
|
69
|
+
message: 'I want something to eat',
|
|
70
|
+
type: 'NAVIGATE',
|
|
71
|
+
targetPageId: 'food_page'
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const drinkButton = new AACButton({
|
|
75
|
+
id: 'btn_drink',
|
|
76
|
+
label: 'Drink',
|
|
77
|
+
message: 'I want something to drink',
|
|
78
|
+
type: 'SPEAK'
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
homePage.addButton(greetingButton);
|
|
82
|
+
homePage.addButton(foodButton);
|
|
83
|
+
homePage.addButton(drinkButton);
|
|
84
|
+
tree.addPage(homePage);
|
|
85
|
+
|
|
86
|
+
// Create food page
|
|
87
|
+
const foodPage = new AACPage({
|
|
88
|
+
id: 'food_page',
|
|
89
|
+
name: 'Food Options',
|
|
90
|
+
buttons: []
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
const appleButton = new AACButton({
|
|
94
|
+
id: 'btn_apple',
|
|
95
|
+
label: 'Apple',
|
|
96
|
+
message: 'I want an apple',
|
|
97
|
+
type: 'SPEAK'
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
const backButton = new AACButton({
|
|
101
|
+
id: 'btn_back',
|
|
102
|
+
label: 'Back',
|
|
103
|
+
message: 'Go back to home',
|
|
104
|
+
type: 'NAVIGATE',
|
|
105
|
+
targetPageId: 'home'
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
foodPage.addButton(appleButton);
|
|
109
|
+
foodPage.addButton(backButton);
|
|
110
|
+
tree.addPage(foodPage);
|
|
111
|
+
|
|
112
|
+
tree.rootId = 'home';
|
|
113
|
+
|
|
114
|
+
console.log(`✅ Created communication board with ${Object.keys(tree.pages).length} pages`);
|
|
115
|
+
|
|
116
|
+
console.log('\n' + '='.repeat(50) + '\n');
|
|
117
|
+
|
|
118
|
+
// Example 3: Save to multiple formats
|
|
119
|
+
console.log('💾 Example 3: Cross-Format Conversion');
|
|
120
|
+
|
|
121
|
+
const tempDir = path.join(__dirname, 'temp');
|
|
122
|
+
if (!fs.existsSync(tempDir)) {
|
|
123
|
+
fs.mkdirSync(tempDir);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
try {
|
|
127
|
+
// Save as DOT
|
|
128
|
+
const dotProcessor = new DotProcessor();
|
|
129
|
+
const dotPath = path.join(tempDir, 'demo-board.dot');
|
|
130
|
+
dotProcessor.saveFromTree(tree, dotPath);
|
|
131
|
+
console.log(`✅ Saved as DOT: ${dotPath}`);
|
|
132
|
+
|
|
133
|
+
// Save as OBF
|
|
134
|
+
const obfProcessor = new ObfProcessor();
|
|
135
|
+
const obfPath = path.join(tempDir, 'demo-board.obf');
|
|
136
|
+
obfProcessor.saveFromTree(tree, obfPath);
|
|
137
|
+
console.log(`✅ Saved as OBF: ${obfPath}`);
|
|
138
|
+
|
|
139
|
+
// Verify round-trip integrity
|
|
140
|
+
const reloadedDotTree = dotProcessor.loadIntoTree(dotPath);
|
|
141
|
+
const reloadedObfTree = obfProcessor.loadIntoTree(obfPath);
|
|
142
|
+
|
|
143
|
+
console.log(`🔄 DOT round-trip: ${Object.keys(reloadedDotTree.pages).length} pages`);
|
|
144
|
+
console.log(`🔄 OBF round-trip: ${Object.keys(reloadedObfTree.pages).length} pages`);
|
|
145
|
+
|
|
146
|
+
} catch (error) {
|
|
147
|
+
console.error('❌ Conversion error:', error);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
console.log('\n' + '='.repeat(50) + '\n');
|
|
151
|
+
|
|
152
|
+
// Example 4: Translation workflow
|
|
153
|
+
console.log('🌍 Example 4: Translation Workflow');
|
|
154
|
+
|
|
155
|
+
try {
|
|
156
|
+
const dotPath = path.join(tempDir, 'demo-board.dot');
|
|
157
|
+
if (fs.existsSync(dotPath)) {
|
|
158
|
+
const processor = new DotProcessor();
|
|
159
|
+
|
|
160
|
+
// Extract all text
|
|
161
|
+
const originalTexts = processor.extractTexts(dotPath);
|
|
162
|
+
console.log(`📝 Found ${originalTexts.length} translatable texts:`, originalTexts);
|
|
163
|
+
|
|
164
|
+
// Create Spanish translations
|
|
165
|
+
const translations = new Map([
|
|
166
|
+
['Hello', 'Hola'],
|
|
167
|
+
['Food', 'Comida'],
|
|
168
|
+
['Drink', 'Bebida'],
|
|
169
|
+
['Apple', 'Manzana'],
|
|
170
|
+
['Back', 'Atrás'],
|
|
171
|
+
['Home Page', 'Página Principal'],
|
|
172
|
+
['Food Options', 'Opciones de Comida'],
|
|
173
|
+
['Hello, how are you today?', 'Hola, ¿cómo estás hoy?'],
|
|
174
|
+
['I want something to eat', 'Quiero algo de comer'],
|
|
175
|
+
['I want something to drink', 'Quiero algo de beber'],
|
|
176
|
+
['I want an apple', 'Quiero una manzana'],
|
|
177
|
+
['Go back to home', 'Volver a casa']
|
|
178
|
+
]);
|
|
179
|
+
|
|
180
|
+
// Apply translations
|
|
181
|
+
const spanishPath = path.join(tempDir, 'demo-board-spanish.dot');
|
|
182
|
+
const translatedBuffer = processor.processTexts(dotPath, translations, spanishPath);
|
|
183
|
+
|
|
184
|
+
console.log(`✅ Applied ${translations.size} translations`);
|
|
185
|
+
console.log(`💾 Saved Spanish version: ${spanishPath}`);
|
|
186
|
+
|
|
187
|
+
// Verify translations
|
|
188
|
+
const spanishTexts = processor.extractTexts(spanishPath);
|
|
189
|
+
console.log(`🔍 Spanish texts:`, spanishTexts.slice(0, 5), '...');
|
|
190
|
+
|
|
191
|
+
} else {
|
|
192
|
+
console.log('⚠️ DOT file not found for translation demo');
|
|
193
|
+
}
|
|
194
|
+
} catch (error) {
|
|
195
|
+
console.error('❌ Translation error:', error);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
console.log('\n' + '='.repeat(50) + '\n');
|
|
199
|
+
|
|
200
|
+
// Example 5: Error handling
|
|
201
|
+
console.log('🛡️ Example 5: Error Handling');
|
|
202
|
+
|
|
203
|
+
try {
|
|
204
|
+
const processor = new DotProcessor();
|
|
205
|
+
|
|
206
|
+
// Try to load a non-existent file
|
|
207
|
+
try {
|
|
208
|
+
processor.loadIntoTree('non-existent-file.dot');
|
|
209
|
+
} catch (error) {
|
|
210
|
+
console.log(`✅ Caught expected error: ${error instanceof Error ? error.message : error}`);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Try to load invalid content
|
|
214
|
+
try {
|
|
215
|
+
const invalidContent = Buffer.from('This is not a valid DOT file');
|
|
216
|
+
const tree = processor.loadIntoTree(invalidContent);
|
|
217
|
+
console.log(`✅ Gracefully handled invalid content: ${Object.keys(tree.pages).length} pages`);
|
|
218
|
+
} catch (error) {
|
|
219
|
+
console.log(`✅ Handled invalid content error: ${error instanceof Error ? error.message : error}`);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
} catch (error) {
|
|
223
|
+
console.error('❌ Error handling demo failed:', error);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
console.log('\n🎉 Demo completed successfully!');
|
|
227
|
+
console.log('\n📚 For more examples, see:');
|
|
228
|
+
console.log(' - README.md for API documentation');
|
|
229
|
+
console.log(' - test/ directory for comprehensive usage examples');
|
|
230
|
+
console.log(' - examples/ directory for more demos');
|
|
231
|
+
|
|
232
|
+
// Cleanup
|
|
233
|
+
try {
|
|
234
|
+
if (fs.existsSync(tempDir)) {
|
|
235
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
236
|
+
console.log('\n🧹 Cleaned up temporary files');
|
|
237
|
+
}
|
|
238
|
+
} catch (error) {
|
|
239
|
+
console.warn('⚠️ Failed to clean up temporary files:', error);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Run the demo
|
|
244
|
+
if (require.main === module) {
|
|
245
|
+
main().catch(error => {
|
|
246
|
+
console.error('❌ Demo failed:', error);
|
|
247
|
+
process.exit(1);
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
export { main as runDemo };
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
#!/usr/bin/env ts-node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Demonstration of the unified alias interface for aac-tools-platform integration
|
|
5
|
+
* Shows how all processors now support consistent method signatures
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
TouchChatProcessor,
|
|
10
|
+
ObfProcessor,
|
|
11
|
+
SnapProcessor,
|
|
12
|
+
DotProcessor,
|
|
13
|
+
GridsetProcessor,
|
|
14
|
+
ApplePanelsProcessor,
|
|
15
|
+
AstericsGridProcessor,
|
|
16
|
+
ExcelProcessor,
|
|
17
|
+
OpmlProcessor,
|
|
18
|
+
StringCasing,
|
|
19
|
+
detectCasing,
|
|
20
|
+
ExtractStringsResult,
|
|
21
|
+
TranslatedString,
|
|
22
|
+
SourceString
|
|
23
|
+
} from "../src/index";
|
|
24
|
+
|
|
25
|
+
async function demonstrateUnifiedInterface() {
|
|
26
|
+
console.log("🚀 AAC Processors - Unified Interface Demo");
|
|
27
|
+
console.log("==========================================\n");
|
|
28
|
+
|
|
29
|
+
// Create instances of different processors
|
|
30
|
+
const processors = [
|
|
31
|
+
{ name: "TouchChat", processor: new TouchChatProcessor(), extension: ".ce" },
|
|
32
|
+
{ name: "OBF", processor: new ObfProcessor(), extension: ".obf" },
|
|
33
|
+
{ name: "Snap", processor: new SnapProcessor(), extension: ".spb" },
|
|
34
|
+
{ name: "Grid3", processor: new GridsetProcessor(), extension: ".gridset" },
|
|
35
|
+
{ name: "Apple Panels", processor: new ApplePanelsProcessor(), extension: ".ascconfig" },
|
|
36
|
+
{ name: "Asterics Grid", processor: new AstericsGridProcessor(), extension: ".grd" },
|
|
37
|
+
{ name: "Excel", processor: new ExcelProcessor(), extension: ".xlsx" },
|
|
38
|
+
{ name: "OPML", processor: new OpmlProcessor(), extension: ".opml" },
|
|
39
|
+
{ name: "DOT", processor: new DotProcessor(), extension: ".dot" }
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
console.log("1. 📋 Checking Unified Interface Availability");
|
|
43
|
+
console.log("----------------------------------------------");
|
|
44
|
+
|
|
45
|
+
processors.forEach(({ name, processor }) => {
|
|
46
|
+
const hasExtractMethod = typeof processor.extractStringsWithMetadata === 'function';
|
|
47
|
+
const hasGenerateMethod = typeof processor.generateTranslatedDownload === 'function';
|
|
48
|
+
|
|
49
|
+
console.log(`${name} Processor:`);
|
|
50
|
+
console.log(` ✅ extractStringsWithMetadata: ${hasExtractMethod ? 'Available' : 'Not Available'}`);
|
|
51
|
+
console.log(` ✅ generateTranslatedDownload: ${hasGenerateMethod ? 'Available' : 'Not Available'}`);
|
|
52
|
+
console.log(` ✅ Backward compatibility: ${typeof processor.extractTexts === 'function' ? 'Maintained' : 'Broken'}`);
|
|
53
|
+
console.log();
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
console.log("2. 🔤 String Casing Detection Demo");
|
|
57
|
+
console.log("----------------------------------");
|
|
58
|
+
|
|
59
|
+
const testStrings = [
|
|
60
|
+
"Hello World",
|
|
61
|
+
"hello world",
|
|
62
|
+
"HELLO WORLD",
|
|
63
|
+
"helloWorld",
|
|
64
|
+
"HelloWorld",
|
|
65
|
+
"hello_world",
|
|
66
|
+
"HELLO_WORLD",
|
|
67
|
+
"hello-world",
|
|
68
|
+
"Hello-World"
|
|
69
|
+
];
|
|
70
|
+
|
|
71
|
+
testStrings.forEach(str => {
|
|
72
|
+
const casing = detectCasing(str);
|
|
73
|
+
console.log(`"${str}" → ${casing}`);
|
|
74
|
+
});
|
|
75
|
+
console.log();
|
|
76
|
+
|
|
77
|
+
console.log("3. 🔄 Mock Translation Workflow");
|
|
78
|
+
console.log("-------------------------------");
|
|
79
|
+
|
|
80
|
+
// Mock data for demonstration
|
|
81
|
+
const mockExtractedResult: ExtractStringsResult = {
|
|
82
|
+
errors: [],
|
|
83
|
+
extractedStrings: [
|
|
84
|
+
{
|
|
85
|
+
string: "Hello",
|
|
86
|
+
vocabPlacementMeta: {
|
|
87
|
+
vocabLocations: [{
|
|
88
|
+
table: "buttons",
|
|
89
|
+
id: 1,
|
|
90
|
+
column: "LABEL",
|
|
91
|
+
casing: StringCasing.CAPITAL
|
|
92
|
+
}]
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
string: "goodbye",
|
|
97
|
+
vocabPlacementMeta: {
|
|
98
|
+
vocabLocations: [{
|
|
99
|
+
table: "buttons",
|
|
100
|
+
id: 2,
|
|
101
|
+
column: "MESSAGE",
|
|
102
|
+
casing: StringCasing.LOWER
|
|
103
|
+
}]
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
]
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const mockTranslatedStrings: TranslatedString[] = [
|
|
110
|
+
{
|
|
111
|
+
sourcestringid: 1,
|
|
112
|
+
overridestring: "",
|
|
113
|
+
translatedstring: "Hola"
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
sourcestringid: 2,
|
|
117
|
+
overridestring: "Adiós",
|
|
118
|
+
translatedstring: "goodbye_translated"
|
|
119
|
+
}
|
|
120
|
+
];
|
|
121
|
+
|
|
122
|
+
const mockSourceStrings: SourceString[] = [
|
|
123
|
+
{
|
|
124
|
+
id: 1,
|
|
125
|
+
sourcestring: "Hello",
|
|
126
|
+
vocabplacementmetadata: mockExtractedResult.extractedStrings[0].vocabPlacementMeta
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
id: 2,
|
|
130
|
+
sourcestring: "goodbye",
|
|
131
|
+
vocabplacementmetadata: mockExtractedResult.extractedStrings[1].vocabPlacementMeta
|
|
132
|
+
}
|
|
133
|
+
];
|
|
134
|
+
|
|
135
|
+
console.log("📤 Mock Extracted Strings:");
|
|
136
|
+
mockExtractedResult.extractedStrings.forEach((extracted, index) => {
|
|
137
|
+
console.log(` ${index + 1}. "${extracted.string}" (${extracted.vocabPlacementMeta.vocabLocations[0].casing})`);
|
|
138
|
+
console.log(` Location: ${extracted.vocabPlacementMeta.vocabLocations[0].table}.${extracted.vocabPlacementMeta.vocabLocations[0].column}[${extracted.vocabPlacementMeta.vocabLocations[0].id}]`);
|
|
139
|
+
});
|
|
140
|
+
console.log();
|
|
141
|
+
|
|
142
|
+
console.log("🔄 Mock Translation Mapping:");
|
|
143
|
+
mockTranslatedStrings.forEach((translation) => {
|
|
144
|
+
const sourceString = mockSourceStrings.find(s => s.id === translation.sourcestringid);
|
|
145
|
+
const finalTranslation = translation.overridestring || translation.translatedstring;
|
|
146
|
+
console.log(` "${sourceString?.sourcestring}" → "${finalTranslation}"`);
|
|
147
|
+
});
|
|
148
|
+
console.log();
|
|
149
|
+
|
|
150
|
+
console.log("4. 🎯 Processor-Specific Features");
|
|
151
|
+
console.log("---------------------------------");
|
|
152
|
+
|
|
153
|
+
console.log("TouchChat Processor:");
|
|
154
|
+
console.log(" • Extracts from SQLite database within .ce files");
|
|
155
|
+
console.log(" • Handles button labels, messages, and pronunciations");
|
|
156
|
+
console.log(" • Preserves TouchChat-specific metadata");
|
|
157
|
+
console.log();
|
|
158
|
+
|
|
159
|
+
console.log("Generic Processors (OBF, Snap, DOT):");
|
|
160
|
+
console.log(" • Use unified extraction logic from BaseProcessor");
|
|
161
|
+
console.log(" • Extract page names and button content");
|
|
162
|
+
console.log(" • Consistent metadata format across all formats");
|
|
163
|
+
console.log();
|
|
164
|
+
|
|
165
|
+
console.log("5. ✅ Integration Benefits");
|
|
166
|
+
console.log("-------------------------");
|
|
167
|
+
console.log("✅ Unified API: All processors support the same method signatures");
|
|
168
|
+
console.log("✅ Backward Compatible: Existing methods continue to work unchanged");
|
|
169
|
+
console.log("✅ Extensible: Easy to add new AAC formats with consistent interface");
|
|
170
|
+
console.log("✅ Type Safe: Full TypeScript support with proper type definitions");
|
|
171
|
+
console.log("✅ Error Handling: Consistent error format across all processors");
|
|
172
|
+
console.log("✅ Metadata Rich: Detailed location and casing information for translations");
|
|
173
|
+
console.log();
|
|
174
|
+
|
|
175
|
+
console.log("🎉 Demo Complete! The unified interface is ready for aac-tools-platform integration.");
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Run the demo
|
|
179
|
+
if (require.main === module) {
|
|
180
|
+
demonstrateUnifiedInterface().catch(console.error);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export { demonstrateUnifiedInterface };
|
package/package.json
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@willwade/aac-processors",
|
|
3
|
+
"version": "0.0.3",
|
|
4
|
+
"description": "A comprehensive TypeScript library for processing AAC (Augmentative and Alternative Communication) file formats with translation support",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist/**/*",
|
|
9
|
+
"docs/**/*",
|
|
10
|
+
"examples/**/*",
|
|
11
|
+
"README.md",
|
|
12
|
+
"LICENSE"
|
|
13
|
+
],
|
|
14
|
+
"directories": {
|
|
15
|
+
"doc": "docs",
|
|
16
|
+
"example": "examples",
|
|
17
|
+
"test": "test"
|
|
18
|
+
},
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "rimraf dist && mkdir dist && ./node_modules/typescript/bin/tsc",
|
|
21
|
+
"build:watch": "tsc --watch",
|
|
22
|
+
"clean": "rimraf dist coverage",
|
|
23
|
+
"lint": "eslint 'src/**/*.{js,ts}' 'test/**/*.{js,ts}'",
|
|
24
|
+
"lint:fix": "eslint 'src/**/*.{js,ts}' 'test/**/*.{js,ts}' --fix",
|
|
25
|
+
"format": "prettier --write 'src/**/*.{js,ts}' 'test/**/*.{js,ts}' '*.{js,ts,json,md}'",
|
|
26
|
+
"format:check": "prettier --check 'src/**/*.{js,ts}' 'test/**/*.{js,ts}' '*.{js,ts,json,md}'",
|
|
27
|
+
"test": "npm run build && jest",
|
|
28
|
+
"test:watch": "npm run build && jest --watch",
|
|
29
|
+
"test:coverage": "npm run build && jest --coverage",
|
|
30
|
+
"test:ci": "npm run build && jest --coverage --ci --watchAll=false --testTimeout=30000",
|
|
31
|
+
"coverage:report": "node scripts/coverage-analysis.js",
|
|
32
|
+
"type-check": "tsc --noEmit",
|
|
33
|
+
"prepublishOnly": "npm run build",
|
|
34
|
+
"prepack": "npm run build"
|
|
35
|
+
},
|
|
36
|
+
"keywords": [
|
|
37
|
+
"aac",
|
|
38
|
+
"augmentative-communication",
|
|
39
|
+
"alternative-communication",
|
|
40
|
+
"assistive-technology",
|
|
41
|
+
"accessibility",
|
|
42
|
+
"communication-boards",
|
|
43
|
+
"snap",
|
|
44
|
+
"grid3",
|
|
45
|
+
"touchchat",
|
|
46
|
+
"obf",
|
|
47
|
+
"opml",
|
|
48
|
+
"dot",
|
|
49
|
+
"typescript",
|
|
50
|
+
"translation",
|
|
51
|
+
"i18n"
|
|
52
|
+
],
|
|
53
|
+
"author": {
|
|
54
|
+
"name": "Will Wade",
|
|
55
|
+
"email": "wwade@acecentre.org.uk",
|
|
56
|
+
"url": "https://github.com/willwade"
|
|
57
|
+
},
|
|
58
|
+
"license": "MIT",
|
|
59
|
+
"publishConfig": {
|
|
60
|
+
"access": "public"
|
|
61
|
+
},
|
|
62
|
+
"repository": {
|
|
63
|
+
"type": "git",
|
|
64
|
+
"url": "https://github.com/willwade/AACProcessors-nodejs.git"
|
|
65
|
+
},
|
|
66
|
+
"bugs": {
|
|
67
|
+
"url": "https://github.com/willwade/AACProcessors-nodejs/issues"
|
|
68
|
+
},
|
|
69
|
+
"homepage": "https://github.com/willwade/AACProcessors-nodejs#readme",
|
|
70
|
+
"engines": {
|
|
71
|
+
"node": ">=16.0.0",
|
|
72
|
+
"npm": ">=8.0.0"
|
|
73
|
+
},
|
|
74
|
+
"devDependencies": {
|
|
75
|
+
"@types/adm-zip": "^0.5.7",
|
|
76
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
77
|
+
"@types/exceljs": "^0.5.3",
|
|
78
|
+
"@types/jest": "^29.5.12",
|
|
79
|
+
"@types/node": "^20.11.24",
|
|
80
|
+
"@types/plist": "^3.0.5",
|
|
81
|
+
"@typescript-eslint/eslint-plugin": "^7.1.0",
|
|
82
|
+
"@typescript-eslint/parser": "^7.1.0",
|
|
83
|
+
"eslint": "^8.56.0",
|
|
84
|
+
"eslint-config-prettier": "^9.1.0",
|
|
85
|
+
"eslint-plugin-prettier": "^5.1.3",
|
|
86
|
+
"fast-check": "^4.2.0",
|
|
87
|
+
"jest": "^29.7.0",
|
|
88
|
+
"prettier": "^3.5.3",
|
|
89
|
+
"rimraf": "^5.0.5",
|
|
90
|
+
"ts-jest": "^29.1.2",
|
|
91
|
+
"typescript": "~5.5.0"
|
|
92
|
+
},
|
|
93
|
+
"dependencies": {
|
|
94
|
+
"adm-zip": "^0.5.16",
|
|
95
|
+
"axios": "^1.11.0",
|
|
96
|
+
"better-sqlite3": "^11.9.1",
|
|
97
|
+
"commander": "^13.1.0",
|
|
98
|
+
"exceljs": "^4.4.0",
|
|
99
|
+
"fast-xml-parser": "^5.2.0",
|
|
100
|
+
"plist": "^3.1.0",
|
|
101
|
+
"yauzl": "^3.2.0"
|
|
102
|
+
},
|
|
103
|
+
"bin": {
|
|
104
|
+
"aac-processors": "./dist/cli/index.js"
|
|
105
|
+
}
|
|
106
|
+
}
|