@willwade/aac-processors 0.0.10 → 0.0.11

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.
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Grid 3 Symbol Search Implementation
3
+ *
4
+ * The .pix files are simple text mappings:
5
+ * searchTerm=symbolFilename=searchTerm
6
+ *
7
+ * Example:
8
+ * above bw=above bw.png=above bw
9
+ * active family=active family.png=active family
10
+ */
11
+ /**
12
+ * Symbol search result
13
+ */
14
+ export interface SymbolSearchResult {
15
+ searchTerm: string;
16
+ symbolFilename: string;
17
+ displayName: string;
18
+ library: string;
19
+ exactMatch: boolean;
20
+ }
21
+ /**
22
+ * Symbol search options
23
+ */
24
+ export interface SymbolSearchOptions {
25
+ grid3Path?: string;
26
+ locale?: string;
27
+ libraries?: string[];
28
+ limit?: number;
29
+ fuzzyMatch?: boolean;
30
+ }
31
+ /**
32
+ * Search index for a single library
33
+ */
34
+ export interface LibrarySearchIndex {
35
+ library: string;
36
+ searchTerms: Map<string, string>;
37
+ filenames: Map<string, string>;
38
+ }
39
+ /**
40
+ * Parse a .pix file into search index
41
+ * @param pixFilePath - Path to .pix file
42
+ * @returns Search index
43
+ */
44
+ export declare function parsePixFile(pixFilePath: string): LibrarySearchIndex;
45
+ /**
46
+ * Load search indexes for all available libraries
47
+ * @param options - Search options
48
+ * @returns Map of library name to search index
49
+ */
50
+ export declare function loadSearchIndexes(options?: SymbolSearchOptions): Map<string, LibrarySearchIndex>;
51
+ /**
52
+ * Search for symbols by term
53
+ * @param searchTerm - Term to search for
54
+ * @param options - Search options
55
+ * @returns Array of search results
56
+ */
57
+ export declare function searchSymbols(searchTerm: string, options?: SymbolSearchOptions): SymbolSearchResult[];
58
+ /**
59
+ * Get symbol filename for a specific search term
60
+ * @param searchTerm - Search term to look up
61
+ * @param library - Library name
62
+ * @param options - Search options
63
+ * @returns Symbol filename or undefined
64
+ */
65
+ export declare function getSymbolFilename(searchTerm: string, library: string, options?: SymbolSearchOptions): string | undefined;
66
+ /**
67
+ * Get display name for a symbol filename
68
+ * @param symbolFilename - Symbol filename (e.g., "above bw.png")
69
+ * @param library - Library name
70
+ * @param options - Search options
71
+ * @returns Display name or undefined
72
+ */
73
+ export declare function getSymbolDisplayName(symbolFilename: string, library: string, options?: SymbolSearchOptions): string | undefined;
74
+ /**
75
+ * Get all search terms for a library
76
+ * @param library - Library name
77
+ * @param options - Search options
78
+ * @returns Array of search terms
79
+ */
80
+ export declare function getAllSearchTerms(library: string, options?: SymbolSearchOptions): string[];
81
+ /**
82
+ * Search suggestions (autocomplete)
83
+ * @param partialTerm - Partial search term
84
+ * @param options - Search options
85
+ * @returns Array of suggested terms
86
+ */
87
+ export declare function getSearchSuggestions(partialTerm: string, options?: SymbolSearchOptions): string[];
88
+ /**
89
+ * Search for symbols and return results with library references
90
+ * @param searchTerm - Term to search for
91
+ * @param options - Search options
92
+ * @returns Array of full symbol references
93
+ */
94
+ export declare function searchSymbolsWithReferences(searchTerm: string, options?: SymbolSearchOptions): string[];
95
+ /**
96
+ * Count symbols in each library
97
+ * @param options - Search options
98
+ * @returns Map of library name to symbol count
99
+ */
100
+ export declare function countLibrarySymbols(options?: SymbolSearchOptions): Map<string, number>;
101
+ /**
102
+ * Get statistics about symbol libraries
103
+ */
104
+ export interface SymbolSearchStats {
105
+ totalLibraries: number;
106
+ totalSymbols: number;
107
+ libraries: Record<string, {
108
+ symbolCount: number;
109
+ exampleTerms: string[];
110
+ }>;
111
+ }
112
+ /**
113
+ * Get symbol search statistics
114
+ * @param options - Search options
115
+ * @returns Statistics about available symbols
116
+ */
117
+ export declare function getSymbolSearchStats(options?: SymbolSearchOptions): SymbolSearchStats;
@@ -0,0 +1,280 @@
1
+ "use strict";
2
+ /**
3
+ * Grid 3 Symbol Search Implementation
4
+ *
5
+ * The .pix files are simple text mappings:
6
+ * searchTerm=symbolFilename=searchTerm
7
+ *
8
+ * Example:
9
+ * above bw=above bw.png=above bw
10
+ * active family=active family.png=active family
11
+ */
12
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ var desc = Object.getOwnPropertyDescriptor(m, k);
15
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
16
+ desc = { enumerable: true, get: function() { return m[k]; } };
17
+ }
18
+ Object.defineProperty(o, k2, desc);
19
+ }) : (function(o, m, k, k2) {
20
+ if (k2 === undefined) k2 = k;
21
+ o[k2] = m[k];
22
+ }));
23
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
24
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
25
+ }) : function(o, v) {
26
+ o["default"] = v;
27
+ });
28
+ var __importStar = (this && this.__importStar) || function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.parsePixFile = parsePixFile;
37
+ exports.loadSearchIndexes = loadSearchIndexes;
38
+ exports.searchSymbols = searchSymbols;
39
+ exports.getSymbolFilename = getSymbolFilename;
40
+ exports.getSymbolDisplayName = getSymbolDisplayName;
41
+ exports.getAllSearchTerms = getAllSearchTerms;
42
+ exports.getSearchSuggestions = getSearchSuggestions;
43
+ exports.searchSymbolsWithReferences = searchSymbolsWithReferences;
44
+ exports.countLibrarySymbols = countLibrarySymbols;
45
+ exports.getSymbolSearchStats = getSymbolSearchStats;
46
+ const fs = __importStar(require("fs"));
47
+ const path = __importStar(require("path"));
48
+ /**
49
+ * Parse a .pix file into search index
50
+ * @param pixFilePath - Path to .pix file
51
+ * @returns Search index
52
+ */
53
+ function parsePixFile(pixFilePath) {
54
+ const content = fs.readFileSync(pixFilePath, 'utf-8');
55
+ const library = path.basename(pixFilePath, '.pix');
56
+ const searchTerms = new Map();
57
+ const filenames = new Map();
58
+ const lines = content.split('\n');
59
+ for (const line of lines) {
60
+ const trimmed = line.trim();
61
+ if (!trimmed || trimmed.startsWith('encoding=')) {
62
+ continue;
63
+ }
64
+ // Format: searchTerm=symbolFilename=searchTerm
65
+ const parts = trimmed.split('=');
66
+ if (parts.length >= 3) {
67
+ const searchTerm = parts[0];
68
+ const symbolFilename = parts[1];
69
+ const displayName = parts[2];
70
+ searchTerms.set(searchTerm.toLowerCase(), symbolFilename);
71
+ filenames.set(symbolFilename, displayName || searchTerm);
72
+ }
73
+ }
74
+ return { library, searchTerms, filenames };
75
+ }
76
+ /**
77
+ * Load search indexes for all available libraries
78
+ * @param options - Search options
79
+ * @returns Map of library name to search index
80
+ */
81
+ function loadSearchIndexes(options = {}) {
82
+ const { grid3Path, locale = 'en-GB', libraries: specifiedLibs } = options;
83
+ if (!grid3Path) {
84
+ throw new Error('grid3Path is required for symbol search');
85
+ }
86
+ const searchIndexesDir = path.join(grid3Path, 'Locale', locale, 'symbolsearch');
87
+ if (!fs.existsSync(searchIndexesDir)) {
88
+ throw new Error(`Symbol search directory not found: ${searchIndexesDir}`);
89
+ }
90
+ const indexes = new Map();
91
+ const files = fs.readdirSync(searchIndexesDir);
92
+ for (const file of files) {
93
+ if (!file.endsWith('.pix')) {
94
+ continue;
95
+ }
96
+ const libraryName = path.basename(file, '.pix');
97
+ // Filter libraries if specified
98
+ if (specifiedLibs && specifiedLibs.length > 0) {
99
+ if (!specifiedLibs.some((lib) => lib.toLowerCase() === libraryName.toLowerCase())) {
100
+ continue;
101
+ }
102
+ }
103
+ try {
104
+ const pixFilePath = path.join(searchIndexesDir, file);
105
+ const index = parsePixFile(pixFilePath);
106
+ indexes.set(libraryName, index);
107
+ }
108
+ catch (error) {
109
+ console.warn(`Failed to load index for ${libraryName}:`, error);
110
+ }
111
+ }
112
+ return indexes;
113
+ }
114
+ /**
115
+ * Search for symbols by term
116
+ * @param searchTerm - Term to search for
117
+ * @param options - Search options
118
+ * @returns Array of search results
119
+ */
120
+ function searchSymbols(searchTerm, options = {}) {
121
+ const indexes = loadSearchIndexes(options);
122
+ const results = [];
123
+ const lowerSearchTerm = searchTerm.toLowerCase().trim();
124
+ const limit = options.limit || 100;
125
+ for (const [libraryName, index] of indexes.entries()) {
126
+ // Exact match first
127
+ if (index.searchTerms.has(lowerSearchTerm)) {
128
+ const symbolFilename = index.searchTerms.get(lowerSearchTerm);
129
+ results.push({
130
+ searchTerm: lowerSearchTerm,
131
+ symbolFilename,
132
+ displayName: index.filenames.get(symbolFilename) || lowerSearchTerm,
133
+ library: libraryName,
134
+ exactMatch: true,
135
+ });
136
+ }
137
+ // Fuzzy match if enabled
138
+ if (options.fuzzyMatch !== false) {
139
+ for (const [term, symbolFilename] of index.searchTerms.entries()) {
140
+ if (term.includes(lowerSearchTerm) || lowerSearchTerm.includes(term)) {
141
+ // Skip if already added as exact match
142
+ if (results.some((r) => r.library === libraryName && r.symbolFilename === symbolFilename)) {
143
+ continue;
144
+ }
145
+ results.push({
146
+ searchTerm: lowerSearchTerm,
147
+ symbolFilename,
148
+ displayName: index.filenames.get(symbolFilename) || term,
149
+ library: libraryName,
150
+ exactMatch: false,
151
+ });
152
+ }
153
+ }
154
+ }
155
+ }
156
+ // Sort by exact match first, then by library
157
+ results.sort((a, b) => {
158
+ if (a.exactMatch !== b.exactMatch) {
159
+ return a.exactMatch ? -1 : 1;
160
+ }
161
+ return a.library.localeCompare(b.library);
162
+ });
163
+ return results.slice(0, limit);
164
+ }
165
+ /**
166
+ * Get symbol filename for a specific search term
167
+ * @param searchTerm - Search term to look up
168
+ * @param library - Library name
169
+ * @param options - Search options
170
+ * @returns Symbol filename or undefined
171
+ */
172
+ function getSymbolFilename(searchTerm, library, options = {}) {
173
+ const indexes = loadSearchIndexes({
174
+ ...options,
175
+ libraries: [library],
176
+ });
177
+ const index = indexes.get(library.toLowerCase());
178
+ if (!index) {
179
+ return undefined;
180
+ }
181
+ return index.searchTerms.get(searchTerm.toLowerCase());
182
+ }
183
+ /**
184
+ * Get display name for a symbol filename
185
+ * @param symbolFilename - Symbol filename (e.g., "above bw.png")
186
+ * @param library - Library name
187
+ * @param options - Search options
188
+ * @returns Display name or undefined
189
+ */
190
+ function getSymbolDisplayName(symbolFilename, library, options = {}) {
191
+ const indexes = loadSearchIndexes({
192
+ ...options,
193
+ libraries: [library],
194
+ });
195
+ const index = indexes.get(library.toLowerCase());
196
+ if (!index) {
197
+ return undefined;
198
+ }
199
+ return index.filenames.get(symbolFilename);
200
+ }
201
+ /**
202
+ * Get all search terms for a library
203
+ * @param library - Library name
204
+ * @param options - Search options
205
+ * @returns Array of search terms
206
+ */
207
+ function getAllSearchTerms(library, options = {}) {
208
+ const indexes = loadSearchIndexes({
209
+ ...options,
210
+ libraries: [library],
211
+ });
212
+ const index = indexes.get(library.toLowerCase());
213
+ if (!index) {
214
+ return [];
215
+ }
216
+ return Array.from(index.searchTerms.keys());
217
+ }
218
+ /**
219
+ * Search suggestions (autocomplete)
220
+ * @param partialTerm - Partial search term
221
+ * @param options - Search options
222
+ * @returns Array of suggested terms
223
+ */
224
+ function getSearchSuggestions(partialTerm, options = {}) {
225
+ const indexes = loadSearchIndexes(options);
226
+ const suggestions = new Set();
227
+ const lowerPartial = partialTerm.toLowerCase().trim();
228
+ for (const index of indexes.values()) {
229
+ for (const term of index.searchTerms.keys()) {
230
+ if (term.startsWith(lowerPartial)) {
231
+ suggestions.add(term);
232
+ }
233
+ }
234
+ }
235
+ return Array.from(suggestions).sort().slice(0, 20);
236
+ }
237
+ /**
238
+ * Search for symbols and return results with library references
239
+ * @param searchTerm - Term to search for
240
+ * @param options - Search options
241
+ * @returns Array of full symbol references
242
+ */
243
+ function searchSymbolsWithReferences(searchTerm, options = {}) {
244
+ const results = searchSymbols(searchTerm, options);
245
+ return results.map((r) => `[${r.library}]${r.symbolFilename}`);
246
+ }
247
+ /**
248
+ * Count symbols in each library
249
+ * @param options - Search options
250
+ * @returns Map of library name to symbol count
251
+ */
252
+ function countLibrarySymbols(options = {}) {
253
+ const indexes = loadSearchIndexes(options);
254
+ const counts = new Map();
255
+ for (const [libraryName, index] of indexes.entries()) {
256
+ counts.set(libraryName, index.searchTerms.size);
257
+ }
258
+ return counts;
259
+ }
260
+ /**
261
+ * Get symbol search statistics
262
+ * @param options - Search options
263
+ * @returns Statistics about available symbols
264
+ */
265
+ function getSymbolSearchStats(options = {}) {
266
+ const indexes = loadSearchIndexes(options);
267
+ const stats = {
268
+ totalLibraries: indexes.size,
269
+ totalSymbols: 0,
270
+ libraries: {},
271
+ };
272
+ for (const [libraryName, index] of indexes.entries()) {
273
+ stats.totalSymbols += index.searchTerms.size;
274
+ stats.libraries[libraryName] = {
275
+ symbolCount: index.searchTerms.size,
276
+ exampleTerms: Array.from(index.searchTerms.keys()).slice(0, 10),
277
+ };
278
+ }
279
+ return stats;
280
+ }
@@ -0,0 +1,199 @@
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
+ /**
16
+ * Known symbol libraries in Grid 3
17
+ */
18
+ export declare const SYMBOL_LIBRARIES: {
19
+ readonly WIDGIT: "widgit";
20
+ readonly TAWASL: "tawasl";
21
+ readonly SSNAPS: "ssnaps";
22
+ readonly GRID3X: "grid3x";
23
+ readonly GRID2X: "grid2x";
24
+ readonly BLISSX: "blissx";
25
+ readonly EYEGAZ: "eyegaz";
26
+ readonly INTERL: "interl";
27
+ readonly METACM: "metacm";
28
+ readonly MJPCS: "mjpcs#";
29
+ readonly PCSHC: "pcshc#";
30
+ readonly PCSTL: "pcstl#";
31
+ readonly SESENS: "sesens";
32
+ readonly SSTIX: "sstix#";
33
+ readonly SYMOJI: "symoji";
34
+ };
35
+ export type SymbolLibraryName = (typeof SYMBOL_LIBRARIES)[keyof typeof SYMBOL_LIBRARIES];
36
+ /**
37
+ * Symbol reference parsed from Grid 3 format
38
+ */
39
+ export interface SymbolReference {
40
+ library: string;
41
+ path: string;
42
+ fullReference: string;
43
+ isValid: boolean;
44
+ }
45
+ /**
46
+ * Symbol library information
47
+ */
48
+ export interface SymbolLibraryInfo {
49
+ name: string;
50
+ pixFile: string;
51
+ exists: boolean;
52
+ size: number;
53
+ locale: string;
54
+ }
55
+ /**
56
+ * Symbol resolution options
57
+ */
58
+ export interface SymbolResolutionOptions {
59
+ grid3Path?: string;
60
+ symbolDir?: string;
61
+ locale?: string;
62
+ fallbackToEmbed?: boolean;
63
+ }
64
+ /**
65
+ * Symbol resolution result
66
+ */
67
+ export interface SymbolResolutionResult {
68
+ reference: SymbolReference;
69
+ found: boolean;
70
+ path?: string;
71
+ data?: Buffer;
72
+ libraryInfo?: SymbolLibraryInfo;
73
+ error?: string;
74
+ }
75
+ /**
76
+ * Default locale to use
77
+ */
78
+ export declare const DEFAULT_LOCALE = "en-GB";
79
+ /**
80
+ * Parse a symbol reference string
81
+ * @param reference - Symbol reference like "[widgit]/food/apple.png"
82
+ * @returns Parsed symbol reference
83
+ */
84
+ export declare function parseSymbolReference(reference: string): SymbolReference;
85
+ /**
86
+ * Check if a string is a symbol library reference
87
+ * @param reference - String to check
88
+ * @returns True if it's a symbol reference like [widgit]/...
89
+ */
90
+ export declare function isSymbolReference(reference: string): boolean;
91
+ /**
92
+ * Get the default Grid 3 installation path for the current platform
93
+ * @returns Default Grid 3 path or empty string if not found
94
+ */
95
+ export declare function getDefaultGrid3Path(): string;
96
+ /**
97
+ * Get the Symbol Libraries directory path
98
+ * Contains .symbols ZIP archives with actual image files
99
+ * @param grid3Path - Grid 3 installation path
100
+ * @returns Path to Symbol Libraries directory (e.g., "C:\...\Grid 3\Resources\Symbols")
101
+ */
102
+ export declare function getSymbolLibrariesDir(grid3Path: string): string;
103
+ /**
104
+ * Get the symbol search indexes directory path for a given locale
105
+ * Contains .pix index files for searching symbols
106
+ * @param grid3Path - Grid 3 installation path
107
+ * @param locale - Locale code (e.g., 'en-GB')
108
+ * @returns Path to symbol search indexes directory (e.g., "C:\...\Grid 3\Locale\en-GB\symbolsearch")
109
+ */
110
+ export declare function getSymbolSearchIndexesDir(grid3Path: string, locale?: string): string;
111
+ /**
112
+ * Get all available symbol libraries in the Grid 3 installation
113
+ * @param options - Resolution options
114
+ * @returns Array of symbol library information
115
+ */
116
+ export declare function getAvailableSymbolLibraries(options?: SymbolResolutionOptions): SymbolLibraryInfo[];
117
+ /**
118
+ * Check if a symbol library exists
119
+ * @param libraryName - Name of the library (e.g., 'widgit', 'tawasl')
120
+ * @param options - Resolution options
121
+ * @returns Symbol library info or undefined if not found
122
+ */
123
+ export declare function getSymbolLibraryInfo(libraryName: string, options?: SymbolResolutionOptions): SymbolLibraryInfo | undefined;
124
+ /**
125
+ * Resolve a symbol reference to extract the actual image data
126
+ * @param reference - Symbol reference like "[tawasl]/above bw.png"
127
+ * @param options - Resolution options
128
+ * @returns Resolution result with image data if found
129
+ */
130
+ export declare function resolveSymbolReference(reference: string, options?: SymbolResolutionOptions): SymbolResolutionResult;
131
+ /**
132
+ * Get all symbol references from a gridset
133
+ * This scans button images for symbol references
134
+ * @param tree - AAC tree from loaded gridset
135
+ * @returns Array of unique symbol references
136
+ */
137
+ export declare function extractSymbolReferences(tree: any): string[];
138
+ /**
139
+ * Create a symbol reference from library and path
140
+ * @param library - Library name
141
+ * @param symbolPath - Path within the library
142
+ * @returns Formatted symbol reference
143
+ */
144
+ export declare function createSymbolReference(library: string, symbolPath: string): string;
145
+ /**
146
+ * Get the library name from a symbol reference
147
+ * @param reference - Symbol reference
148
+ * @returns Library name or empty string
149
+ */
150
+ export declare function getSymbolLibraryName(reference: string): string;
151
+ /**
152
+ * Get the symbol path from a symbol reference
153
+ * @param reference - Symbol reference
154
+ * @returns Symbol path or empty string
155
+ */
156
+ export declare function getSymbolPath(reference: string): string;
157
+ /**
158
+ * Check if a symbol library is one of the known Grid 3 libraries
159
+ * @param libraryName - Library name to check
160
+ * @returns True if it's a known library
161
+ */
162
+ export declare function isKnownSymbolLibrary(libraryName: string): boolean;
163
+ /**
164
+ * Get display name for a symbol library
165
+ * @param libraryName - Library name
166
+ * @returns Human-readable display name
167
+ */
168
+ export declare function getSymbolLibraryDisplayName(libraryName: string): string;
169
+ /**
170
+ * Analyze symbol usage in a gridset
171
+ * @param tree - AAC tree from loaded gridset
172
+ * @returns Symbol usage statistics
173
+ */
174
+ export interface SymbolUsageStats {
175
+ totalSymbols: number;
176
+ byLibrary: Record<string, number>;
177
+ uniqueReferences: string[];
178
+ librariesUsed: string[];
179
+ }
180
+ export declare function analyzeSymbolUsage(tree: any): SymbolUsageStats;
181
+ /**
182
+ * Convert symbol reference to filename for embedded images
183
+ * Grid 3 sometimes embeds symbols with special naming
184
+ * @param reference - Symbol reference
185
+ * @param cellX - Cell X coordinate
186
+ * @param cellY - Cell Y coordinate
187
+ * @returns Generated filename
188
+ */
189
+ export declare function symbolReferenceToFilename(reference: string, cellX: number, cellY: number): string;
190
+ /**
191
+ * @deprecated Use getSymbolLibrariesDir() instead - more descriptive name
192
+ * Get the Symbols directory path (where .symbols ZIP archives are)
193
+ */
194
+ export declare function getSymbolsDir(grid3Path: string): string;
195
+ /**
196
+ * @deprecated Use getSymbolSearchIndexesDir() instead - more descriptive name
197
+ * Get the symbol search directory for a given locale (where .pix index files are)
198
+ */
199
+ export declare function getSymbolSearchDir(grid3Path: string, locale?: string): string;