@willwade/aac-processors 0.0.30 → 0.1.1

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 (94) hide show
  1. package/README.md +52 -852
  2. package/dist/browser/core/baseProcessor.js +241 -0
  3. package/dist/browser/core/stringCasing.js +179 -0
  4. package/dist/browser/core/treeStructure.js +255 -0
  5. package/dist/browser/index.browser.js +73 -0
  6. package/dist/browser/processors/applePanelsProcessor.js +582 -0
  7. package/dist/browser/processors/astericsGridProcessor.js +1509 -0
  8. package/dist/browser/processors/dotProcessor.js +221 -0
  9. package/dist/browser/processors/gridset/commands.js +962 -0
  10. package/dist/browser/processors/gridset/crypto.js +53 -0
  11. package/dist/browser/processors/gridset/password.js +49 -0
  12. package/dist/browser/processors/gridset/pluginTypes.js +277 -0
  13. package/dist/browser/processors/gridset/resolver.js +137 -0
  14. package/dist/browser/processors/gridset/symbolAlignment.js +276 -0
  15. package/dist/browser/processors/gridset/symbols.js +464 -0
  16. package/dist/browser/processors/gridsetProcessor.js +2002 -0
  17. package/dist/browser/processors/obfProcessor.js +705 -0
  18. package/dist/browser/processors/opmlProcessor.js +274 -0
  19. package/dist/browser/types/aac.js +38 -0
  20. package/dist/browser/utilities/analytics/utils/idGenerator.js +89 -0
  21. package/dist/browser/utilities/translation/translationProcessor.js +200 -0
  22. package/dist/browser/utils/io.js +95 -0
  23. package/dist/browser/validation/baseValidator.js +156 -0
  24. package/dist/browser/validation/gridsetValidator.js +356 -0
  25. package/dist/browser/validation/obfValidator.js +500 -0
  26. package/dist/browser/validation/validationTypes.js +46 -0
  27. package/dist/cli/index.js +5 -5
  28. package/dist/core/analyze.d.ts +2 -2
  29. package/dist/core/analyze.js +2 -2
  30. package/dist/core/baseProcessor.d.ts +5 -4
  31. package/dist/core/baseProcessor.js +22 -27
  32. package/dist/core/treeStructure.d.ts +5 -5
  33. package/dist/core/treeStructure.js +1 -4
  34. package/dist/index.browser.d.ts +37 -0
  35. package/dist/index.browser.js +99 -0
  36. package/dist/index.d.ts +1 -48
  37. package/dist/index.js +1 -136
  38. package/dist/index.node.d.ts +48 -0
  39. package/dist/index.node.js +152 -0
  40. package/dist/processors/applePanelsProcessor.d.ts +5 -4
  41. package/dist/processors/applePanelsProcessor.js +58 -62
  42. package/dist/processors/astericsGridProcessor.d.ts +7 -6
  43. package/dist/processors/astericsGridProcessor.js +31 -42
  44. package/dist/processors/dotProcessor.d.ts +5 -4
  45. package/dist/processors/dotProcessor.js +25 -33
  46. package/dist/processors/excelProcessor.d.ts +4 -3
  47. package/dist/processors/excelProcessor.js +6 -3
  48. package/dist/processors/gridset/crypto.d.ts +18 -0
  49. package/dist/processors/gridset/crypto.js +57 -0
  50. package/dist/processors/gridset/helpers.d.ts +1 -1
  51. package/dist/processors/gridset/helpers.js +18 -8
  52. package/dist/processors/gridset/password.d.ts +20 -3
  53. package/dist/processors/gridset/password.js +29 -12
  54. package/dist/processors/gridset/symbols.js +63 -46
  55. package/dist/processors/gridset/wordlistHelpers.d.ts +3 -3
  56. package/dist/processors/gridset/wordlistHelpers.js +21 -20
  57. package/dist/processors/gridsetProcessor.d.ts +7 -12
  58. package/dist/processors/gridsetProcessor.js +116 -77
  59. package/dist/processors/obfProcessor.d.ts +9 -7
  60. package/dist/processors/obfProcessor.js +131 -56
  61. package/dist/processors/obfsetProcessor.d.ts +5 -4
  62. package/dist/processors/obfsetProcessor.js +10 -16
  63. package/dist/processors/opmlProcessor.d.ts +5 -4
  64. package/dist/processors/opmlProcessor.js +27 -34
  65. package/dist/processors/snapProcessor.d.ts +8 -7
  66. package/dist/processors/snapProcessor.js +15 -12
  67. package/dist/processors/touchchatProcessor.d.ts +8 -7
  68. package/dist/processors/touchchatProcessor.js +22 -17
  69. package/dist/types/aac.d.ts +0 -2
  70. package/dist/types/aac.js +2 -0
  71. package/dist/utils/io.d.ts +12 -0
  72. package/dist/utils/io.js +107 -0
  73. package/dist/validation/gridsetValidator.js +10 -9
  74. package/dist/validation/snapValidator.js +28 -35
  75. package/docs/BROWSER_USAGE.md +618 -0
  76. package/docs/PAGESET_GETTING_STARTED.md +185 -0
  77. package/examples/README.md +77 -0
  78. package/examples/browser-test-server.js +81 -0
  79. package/examples/browser-test.html +331 -0
  80. package/examples/vitedemo/QUICKSTART.md +75 -0
  81. package/examples/vitedemo/README.md +157 -0
  82. package/examples/vitedemo/index.html +531 -0
  83. package/examples/vitedemo/package-lock.json +1221 -0
  84. package/examples/vitedemo/package.json +18 -0
  85. package/examples/vitedemo/src/main.ts +871 -0
  86. package/examples/vitedemo/test-files/example.dot +14 -0
  87. package/examples/vitedemo/test-files/example.grd +1 -0
  88. package/examples/vitedemo/test-files/example.gridset +0 -0
  89. package/examples/vitedemo/test-files/example.obz +0 -0
  90. package/examples/vitedemo/test-files/example.opml +18 -0
  91. package/examples/vitedemo/test-files/simple.obf +53 -0
  92. package/examples/vitedemo/tsconfig.json +24 -0
  93. package/examples/vitedemo/vite.config.ts +34 -0
  94. package/package.json +21 -4
@@ -0,0 +1,464 @@
1
+ /**
2
+ * Grid 3 Symbol Library Resolution
3
+ *
4
+ * Grid 3 uses symbol libraries stored as .pix files in the installation directory.
5
+ * Symbol references in Grid files use the format: [library]/path/to/symbol.png
6
+ *
7
+ * Examples:
8
+ * - [widgit]/food/apple.png
9
+ * - [tawasl]/above bw.png
10
+ * - [ssnaps]963.jpg
11
+ * - [grid3x]/folder/document.png
12
+ *
13
+ * This module provides symbol resolution and metadata extraction.
14
+ */
15
+ import { getFs, getPath } from '../../utils/io';
16
+ /**
17
+ * Default Grid 3 installation paths by platform
18
+ */
19
+ const DEFAULT_GRID3_PATHS = {
20
+ win32: 'C:\\Program Files (x86)\\Smartbox\\Grid 3',
21
+ darwin: '/Applications/Grid 3.app/Contents/Resources',
22
+ linux: '/opt/smartbox/grid3',
23
+ };
24
+ /**
25
+ * Path to Symbols directory within Grid 3 installation
26
+ * Contains .symbols ZIP archives with actual images
27
+ */
28
+ const SYMBOLS_SUBDIR = 'Resources\\Symbols';
29
+ /**
30
+ * Path to symbol search indexes within Grid 3 installation
31
+ * Contains .pix index files for searching
32
+ */
33
+ const SYMBOLSEARCH_SUBDIR = 'Locale';
34
+ /**
35
+ * Known symbol libraries in Grid 3
36
+ */
37
+ export const SYMBOL_LIBRARIES = {
38
+ WIDGIT: 'widgit',
39
+ TAWASL: 'tawasl',
40
+ SSNAPS: 'ssnaps',
41
+ GRID3X: 'grid3x',
42
+ GRID2X: 'grid2x',
43
+ BLISSX: 'blissx',
44
+ EYEGAZ: 'eyegaz',
45
+ INTERL: 'interl',
46
+ METACM: 'metacm',
47
+ MJPCS: 'mjpcs#',
48
+ PCSHC: 'pcshc#',
49
+ PCSTL: 'pcstl#',
50
+ SESENS: 'sesens',
51
+ SSTIX: 'sstix#',
52
+ SYMOJI: 'symoji',
53
+ };
54
+ /**
55
+ * Default locale to use
56
+ */
57
+ export const DEFAULT_LOCALE = 'en-GB';
58
+ function getNodeFs() {
59
+ try {
60
+ return getFs();
61
+ }
62
+ catch {
63
+ throw new Error('Symbol library access is not available in this environment.');
64
+ }
65
+ }
66
+ function getNodePath() {
67
+ try {
68
+ return getPath();
69
+ }
70
+ catch {
71
+ throw new Error('Path utilities are not available in this environment.');
72
+ }
73
+ }
74
+ let cachedAdmZip = null;
75
+ function getAdmZip() {
76
+ if (cachedAdmZip)
77
+ return cachedAdmZip;
78
+ try {
79
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
80
+ const module = require('adm-zip');
81
+ const resolved = module.default || module;
82
+ cachedAdmZip = resolved;
83
+ return resolved;
84
+ }
85
+ catch {
86
+ throw new Error('Symbol library access requires AdmZip in this environment.');
87
+ }
88
+ }
89
+ /**
90
+ * Parse a symbol reference string
91
+ * @param reference - Symbol reference like "[widgit]/food/apple.png"
92
+ * @returns Parsed symbol reference
93
+ */
94
+ export function parseSymbolReference(reference) {
95
+ const trimmed = reference.trim();
96
+ // Match pattern: [library]/path or [library]path
97
+ const match = trimmed.match(/^\[([^\]]+)\](.+)$/);
98
+ if (!match) {
99
+ return {
100
+ library: '',
101
+ path: trimmed,
102
+ fullReference: trimmed,
103
+ isValid: false,
104
+ };
105
+ }
106
+ const [, library, symbolPath] = match;
107
+ return {
108
+ library: library.toLowerCase(),
109
+ path: symbolPath.replace(/^\\+/, '').trim(), // Remove leading slashes
110
+ fullReference: trimmed,
111
+ isValid: true,
112
+ };
113
+ }
114
+ /**
115
+ * Check if a string is a symbol library reference
116
+ * @param reference - String to check
117
+ * @returns True if it's a symbol reference like [widgit]/...
118
+ */
119
+ export function isSymbolReference(reference) {
120
+ return reference.trim().startsWith('[');
121
+ }
122
+ /**
123
+ * Get the default Grid 3 installation path for the current platform
124
+ * @returns Default Grid 3 path or empty string if not found
125
+ */
126
+ export function getDefaultGrid3Path() {
127
+ const platform = (typeof process !== 'undefined' && process.platform ? process.platform : 'unknown');
128
+ const defaultPath = DEFAULT_GRID3_PATHS[platform] || '';
129
+ try {
130
+ const fs = getNodeFs();
131
+ if (defaultPath && fs.existsSync(defaultPath)) {
132
+ return defaultPath;
133
+ }
134
+ // Try to find Grid 3 in common locations
135
+ const commonPaths = [
136
+ 'C:\\Program Files (x86)\\Smartbox\\Grid 3',
137
+ 'C:\\Program Files\\Smartbox\\Grid 3',
138
+ 'C:\\Program Files\\Smartbox\\Grid 3',
139
+ '/Applications/Grid 3.app',
140
+ '/opt/smartbox/grid3',
141
+ ];
142
+ for (const testPath of commonPaths) {
143
+ if (fs.existsSync(testPath)) {
144
+ return testPath;
145
+ }
146
+ }
147
+ }
148
+ catch {
149
+ return '';
150
+ }
151
+ return '';
152
+ }
153
+ /**
154
+ * Get the Symbol Libraries directory path
155
+ * Contains .symbols ZIP archives with actual image files
156
+ * @param grid3Path - Grid 3 installation path
157
+ * @returns Path to Symbol Libraries directory (e.g., "C:\...\Grid 3\Resources\Symbols")
158
+ */
159
+ export function getSymbolLibrariesDir(grid3Path) {
160
+ const path = getNodePath();
161
+ return path.join(grid3Path, SYMBOLS_SUBDIR);
162
+ }
163
+ /**
164
+ * Get the symbol search indexes directory path for a given locale
165
+ * Contains .pix index files for searching symbols
166
+ * @param grid3Path - Grid 3 installation path
167
+ * @param locale - Locale code (e.g., 'en-GB')
168
+ * @returns Path to symbol search indexes directory (e.g., "C:\...\Grid 3\Locale\en-GB\symbolsearch")
169
+ */
170
+ export function getSymbolSearchIndexesDir(grid3Path, locale = DEFAULT_LOCALE) {
171
+ const path = getNodePath();
172
+ return path.join(grid3Path, SYMBOLSEARCH_SUBDIR, locale, 'symbolsearch');
173
+ }
174
+ /**
175
+ * Get all available symbol libraries in the Grid 3 installation
176
+ * @param options - Resolution options
177
+ * @returns Array of symbol library information
178
+ */
179
+ export function getAvailableSymbolLibraries(options = {}) {
180
+ const grid3Path = options.grid3Path || options.symbolDir || getDefaultGrid3Path();
181
+ if (!grid3Path) {
182
+ return [];
183
+ }
184
+ const symbolsDir = getSymbolLibrariesDir(grid3Path);
185
+ const fs = getNodeFs();
186
+ if (!fs.existsSync(symbolsDir)) {
187
+ return [];
188
+ }
189
+ const libraries = [];
190
+ const files = fs.readdirSync(symbolsDir);
191
+ for (const file of files) {
192
+ if (file.endsWith('.symbols')) {
193
+ const path = getNodePath();
194
+ const fullPath = path.join(symbolsDir, file);
195
+ const stats = fs.statSync(fullPath);
196
+ const libraryName = path.basename(file, '.symbols');
197
+ libraries.push({
198
+ name: libraryName,
199
+ pixFile: fullPath, // Reuse this field for the .symbols file path
200
+ exists: true,
201
+ size: stats.size,
202
+ locale: 'global', // .symbols files are not locale-specific
203
+ });
204
+ }
205
+ }
206
+ return libraries.sort((a, b) => a.name.localeCompare(b.name));
207
+ }
208
+ /**
209
+ * Check if a symbol library exists
210
+ * @param libraryName - Name of the library (e.g., 'widgit', 'tawasl')
211
+ * @param options - Resolution options
212
+ * @returns Symbol library info or undefined if not found
213
+ */
214
+ export function getSymbolLibraryInfo(libraryName, options = {}) {
215
+ const grid3Path = options.grid3Path || options.symbolDir || getDefaultGrid3Path();
216
+ if (!grid3Path) {
217
+ return undefined;
218
+ }
219
+ const symbolsDir = getSymbolLibrariesDir(grid3Path);
220
+ const normalizedLibName = libraryName.toLowerCase();
221
+ // Try different case variations
222
+ const variations = [
223
+ normalizedLibName + '.symbols',
224
+ normalizedLibName.toUpperCase() + '.symbols',
225
+ libraryName + '.symbols',
226
+ ];
227
+ for (const file of variations) {
228
+ const path = getNodePath();
229
+ const fullPath = path.join(symbolsDir, file);
230
+ const fs = getNodeFs();
231
+ if (fs.existsSync(fullPath)) {
232
+ const stats = fs.statSync(fullPath);
233
+ return {
234
+ name: libraryName,
235
+ pixFile: fullPath,
236
+ exists: true,
237
+ size: stats.size,
238
+ locale: 'global',
239
+ };
240
+ }
241
+ }
242
+ return undefined;
243
+ }
244
+ /**
245
+ * Resolve a symbol reference to extract the actual image data
246
+ * @param reference - Symbol reference like "[tawasl]/above bw.png"
247
+ * @param options - Resolution options
248
+ * @returns Resolution result with image data if found
249
+ */
250
+ export function resolveSymbolReference(reference, options = {}) {
251
+ const parsed = parseSymbolReference(reference);
252
+ if (!parsed.isValid) {
253
+ return {
254
+ reference: parsed,
255
+ found: false,
256
+ error: 'Invalid symbol reference format',
257
+ };
258
+ }
259
+ const grid3Path = options.grid3Path || getDefaultGrid3Path();
260
+ if (!grid3Path) {
261
+ return {
262
+ reference: parsed,
263
+ found: false,
264
+ error: 'Grid 3 installation not found. Please specify grid3Path.',
265
+ };
266
+ }
267
+ const libraryInfo = getSymbolLibraryInfo(parsed.library, { grid3Path });
268
+ if (!libraryInfo || !libraryInfo.exists) {
269
+ return {
270
+ reference: parsed,
271
+ found: false,
272
+ error: `Symbol library '${parsed.library}' not found at ${libraryInfo?.pixFile || 'unknown'}`,
273
+ };
274
+ }
275
+ try {
276
+ // .symbols files are ZIP archives
277
+ const AdmZip = getAdmZip();
278
+ const zip = new AdmZip(libraryInfo.pixFile);
279
+ // The path in the symbol reference becomes the path within the symbols/ folder
280
+ // e.g., [tawasl]/above bw.png becomes symbols/above bw.png
281
+ const symbolPath = `symbols/${parsed.path}`;
282
+ const entry = zip.getEntry(symbolPath);
283
+ if (!entry) {
284
+ // Try without the symbols/ prefix (in case reference already includes it)
285
+ const altPath = parsed.path.startsWith('symbols/') ? parsed.path : `symbols/${parsed.path}`;
286
+ const altEntry = zip.getEntry(altPath);
287
+ if (!altEntry) {
288
+ return {
289
+ reference: parsed,
290
+ found: false,
291
+ error: `Symbol '${parsed.path}' not found in library '${parsed.library}'`,
292
+ path: libraryInfo.pixFile,
293
+ libraryInfo,
294
+ };
295
+ }
296
+ // Found with alternate path
297
+ const data = altEntry.getData();
298
+ return {
299
+ reference: parsed,
300
+ found: true,
301
+ path: libraryInfo.pixFile,
302
+ data,
303
+ libraryInfo,
304
+ };
305
+ }
306
+ // Found the symbol!
307
+ const data = entry.getData();
308
+ return {
309
+ reference: parsed,
310
+ found: true,
311
+ path: libraryInfo.pixFile,
312
+ data,
313
+ libraryInfo,
314
+ };
315
+ }
316
+ catch (error) {
317
+ return {
318
+ reference: parsed,
319
+ found: false,
320
+ error: `Failed to extract symbol: ${error.message}`,
321
+ path: libraryInfo.pixFile,
322
+ libraryInfo,
323
+ };
324
+ }
325
+ }
326
+ /**
327
+ * Get all symbol references from a gridset
328
+ * This scans button images for symbol references
329
+ * @param tree - AAC tree from loaded gridset
330
+ * @returns Array of unique symbol references
331
+ */
332
+ export function extractSymbolReferences(tree) {
333
+ const references = new Set();
334
+ for (const pageId in tree.pages) {
335
+ const page = tree.pages[pageId];
336
+ if (page.buttons) {
337
+ for (const button of page.buttons) {
338
+ if (button.image && isSymbolReference(String(button.image))) {
339
+ references.add(String(button.image));
340
+ }
341
+ // Check for symbol library metadata
342
+ if (button.symbolLibrary) {
343
+ const ref = `[${button.symbolLibrary}]${button.symbolPath || ''}`;
344
+ references.add(ref);
345
+ }
346
+ }
347
+ }
348
+ }
349
+ return Array.from(references).sort();
350
+ }
351
+ /**
352
+ * Create a symbol reference from library and path
353
+ * @param library - Library name
354
+ * @param symbolPath - Path within the library
355
+ * @returns Formatted symbol reference
356
+ */
357
+ export function createSymbolReference(library, symbolPath) {
358
+ const normalizedLib = library.toLowerCase().replace(/\[|\]/g, '');
359
+ const normalizedPath = symbolPath.replace(/^\\+/, '');
360
+ return `[${normalizedLib}]${normalizedPath}`;
361
+ }
362
+ /**
363
+ * Get the library name from a symbol reference
364
+ * @param reference - Symbol reference
365
+ * @returns Library name or empty string
366
+ */
367
+ export function getSymbolLibraryName(reference) {
368
+ const parsed = parseSymbolReference(reference);
369
+ return parsed.library;
370
+ }
371
+ /**
372
+ * Get the symbol path from a symbol reference
373
+ * @param reference - Symbol reference
374
+ * @returns Symbol path or empty string
375
+ */
376
+ export function getSymbolPath(reference) {
377
+ const parsed = parseSymbolReference(reference);
378
+ return parsed.path;
379
+ }
380
+ /**
381
+ * Check if a symbol library is one of the known Grid 3 libraries
382
+ * @param libraryName - Library name to check
383
+ * @returns True if it's a known library
384
+ */
385
+ export function isKnownSymbolLibrary(libraryName) {
386
+ const normalized = libraryName.toLowerCase().replace(/\[|\]/g, '');
387
+ return Object.values(SYMBOL_LIBRARIES).includes(normalized);
388
+ }
389
+ /**
390
+ * Get display name for a symbol library
391
+ * @param libraryName - Library name
392
+ * @returns Human-readable display name
393
+ */
394
+ export function getSymbolLibraryDisplayName(libraryName) {
395
+ const normalized = libraryName.toLowerCase().replace(/\[|\]/g, '');
396
+ const displayNames = {
397
+ widgit: 'Widgit Symbols',
398
+ tawasl: 'Tawasol (Arabic)',
399
+ ssnaps: 'Smartbox Symbol Snapshots',
400
+ grid3x: 'Grid 3 Extended',
401
+ grid2x: 'Grid 2 Extended',
402
+ blissx: 'Blissymbols',
403
+ eyegaz: 'Eye Gaze Symbols',
404
+ interl: 'International Symbols',
405
+ metacm: 'MetaComm',
406
+ mjpcs: 'Mayer-Johnson PCS',
407
+ pcshc: 'PCS High Contrast',
408
+ pcstl: 'PCS Thin Line',
409
+ sesens: 'Sensory Software',
410
+ sstix: 'Smartbox TIX',
411
+ symoji: 'Symbol Emoji',
412
+ };
413
+ return displayNames[normalized] || normalized.charAt(0).toUpperCase() + normalized.slice(1);
414
+ }
415
+ export function analyzeSymbolUsage(tree) {
416
+ const references = extractSymbolReferences(tree);
417
+ const byLibrary = {};
418
+ const libraries = new Set();
419
+ for (const ref of references) {
420
+ const lib = getSymbolLibraryName(ref);
421
+ byLibrary[lib] = (byLibrary[lib] || 0) + 1;
422
+ if (lib) {
423
+ libraries.add(lib);
424
+ }
425
+ }
426
+ return {
427
+ totalSymbols: references.length,
428
+ byLibrary,
429
+ uniqueReferences: references,
430
+ librariesUsed: Array.from(libraries).sort(),
431
+ };
432
+ }
433
+ /**
434
+ * Convert symbol reference to filename for embedded images
435
+ * Grid 3 sometimes embeds symbols with special naming
436
+ * @param reference - Symbol reference
437
+ * @param cellX - Cell X coordinate
438
+ * @param cellY - Cell Y coordinate
439
+ * @returns Generated filename
440
+ */
441
+ export function symbolReferenceToFilename(reference, cellX, cellY) {
442
+ const parsed = parseSymbolReference(reference);
443
+ const dotIndex = parsed.path.lastIndexOf('.');
444
+ const ext = dotIndex >= 0 ? parsed.path.slice(dotIndex) : '.png';
445
+ // Grid 3 format: {x}-{y}-0-text-0.{ext}
446
+ return `${cellX}-${cellY}-0-text-0${ext}`;
447
+ }
448
+ // ============================================================================
449
+ // BACKWARD COMPATIBILITY ALIASES
450
+ // ============================================================================
451
+ /**
452
+ * @deprecated Use getSymbolLibrariesDir() instead - more descriptive name
453
+ * Get the Symbols directory path (where .symbols ZIP archives are)
454
+ */
455
+ export function getSymbolsDir(grid3Path) {
456
+ return getSymbolLibrariesDir(grid3Path);
457
+ }
458
+ /**
459
+ * @deprecated Use getSymbolSearchIndexesDir() instead - more descriptive name
460
+ * Get the symbol search directory for a given locale (where .pix index files are)
461
+ */
462
+ export function getSymbolSearchDir(grid3Path, locale = DEFAULT_LOCALE) {
463
+ return getSymbolSearchIndexesDir(grid3Path, locale);
464
+ }