@willwade/aac-processors 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +787 -0
  3. package/dist/cli/index.d.ts +2 -0
  4. package/dist/cli/index.js +189 -0
  5. package/dist/cli/prettyPrint.d.ts +2 -0
  6. package/dist/cli/prettyPrint.js +28 -0
  7. package/dist/core/analyze.d.ts +6 -0
  8. package/dist/core/analyze.js +49 -0
  9. package/dist/core/baseProcessor.d.ts +94 -0
  10. package/dist/core/baseProcessor.js +208 -0
  11. package/dist/core/fileProcessor.d.ts +7 -0
  12. package/dist/core/fileProcessor.js +51 -0
  13. package/dist/core/stringCasing.d.ts +37 -0
  14. package/dist/core/stringCasing.js +174 -0
  15. package/dist/core/treeStructure.d.ts +190 -0
  16. package/dist/core/treeStructure.js +223 -0
  17. package/dist/index.d.ts +23 -0
  18. package/dist/index.js +96 -0
  19. package/dist/optional/symbolTools.d.ts +28 -0
  20. package/dist/optional/symbolTools.js +126 -0
  21. package/dist/processors/applePanelsProcessor.d.ts +23 -0
  22. package/dist/processors/applePanelsProcessor.js +521 -0
  23. package/dist/processors/astericsGridProcessor.d.ts +49 -0
  24. package/dist/processors/astericsGridProcessor.js +1427 -0
  25. package/dist/processors/dotProcessor.d.ts +21 -0
  26. package/dist/processors/dotProcessor.js +191 -0
  27. package/dist/processors/excelProcessor.d.ts +145 -0
  28. package/dist/processors/excelProcessor.js +556 -0
  29. package/dist/processors/gridset/helpers.d.ts +4 -0
  30. package/dist/processors/gridset/helpers.js +48 -0
  31. package/dist/processors/gridset/resolver.d.ts +8 -0
  32. package/dist/processors/gridset/resolver.js +100 -0
  33. package/dist/processors/gridsetProcessor.d.ts +28 -0
  34. package/dist/processors/gridsetProcessor.js +1339 -0
  35. package/dist/processors/index.d.ts +14 -0
  36. package/dist/processors/index.js +42 -0
  37. package/dist/processors/obfProcessor.d.ts +21 -0
  38. package/dist/processors/obfProcessor.js +278 -0
  39. package/dist/processors/opmlProcessor.d.ts +21 -0
  40. package/dist/processors/opmlProcessor.js +235 -0
  41. package/dist/processors/snap/helpers.d.ts +4 -0
  42. package/dist/processors/snap/helpers.js +27 -0
  43. package/dist/processors/snapProcessor.d.ts +44 -0
  44. package/dist/processors/snapProcessor.js +586 -0
  45. package/dist/processors/touchchat/helpers.d.ts +4 -0
  46. package/dist/processors/touchchat/helpers.js +27 -0
  47. package/dist/processors/touchchatProcessor.d.ts +27 -0
  48. package/dist/processors/touchchatProcessor.js +768 -0
  49. package/dist/types/aac.d.ts +47 -0
  50. package/dist/types/aac.js +2 -0
  51. package/docs/.keep +1 -0
  52. package/docs/ApplePanels.md +309 -0
  53. package/docs/Grid3-XML-Format.md +1788 -0
  54. package/docs/TobiiDynavox-Snap-Details.md +394 -0
  55. package/docs/asterics-Grid-fileformat-details.md +443 -0
  56. package/docs/obf_.obz Open Board File Formats.md +432 -0
  57. package/docs/touchchat.md +520 -0
  58. package/examples/.coverage +0 -0
  59. package/examples/.keep +1 -0
  60. package/examples/README.md +31 -0
  61. package/examples/communikate.dot +2637 -0
  62. package/examples/demo.js +143 -0
  63. package/examples/example-images.gridset +0 -0
  64. package/examples/example.ce +0 -0
  65. package/examples/example.dot +14 -0
  66. package/examples/example.grd +1 -0
  67. package/examples/example.gridset +0 -0
  68. package/examples/example.obf +27 -0
  69. package/examples/example.obz +0 -0
  70. package/examples/example.opml +18 -0
  71. package/examples/example.spb +0 -0
  72. package/examples/example.sps +0 -0
  73. package/examples/example2.grd +1 -0
  74. package/examples/gemini_response.txt +845 -0
  75. package/examples/image-map.js +45 -0
  76. package/examples/package-lock.json +1326 -0
  77. package/examples/package.json +10 -0
  78. package/examples/styled-output/converted-snap-to-touchchat.ce +0 -0
  79. package/examples/styled-output/styled-example.ce +0 -0
  80. package/examples/styled-output/styled-example.gridset +0 -0
  81. package/examples/styled-output/styled-example.obf +37 -0
  82. package/examples/styled-output/styled-example.spb +0 -0
  83. package/examples/styling-example.ts +316 -0
  84. package/examples/translate.js +39 -0
  85. package/examples/translate_demo.js +254 -0
  86. package/examples/translation_cache.json +44894 -0
  87. package/examples/typescript-demo.ts +251 -0
  88. package/examples/unified-interface-demo.ts +183 -0
  89. package/package.json +106 -0
@@ -0,0 +1,21 @@
1
+ import { BaseProcessor, ProcessorOptions, ExtractStringsResult, TranslatedString, SourceString } from '../core/baseProcessor';
2
+ import { AACTree } from '../core/treeStructure';
3
+ declare class DotProcessor extends BaseProcessor {
4
+ constructor(options?: ProcessorOptions);
5
+ private parseDotFile;
6
+ extractTexts(filePathOrBuffer: string | Buffer): string[];
7
+ loadIntoTree(filePathOrBuffer: string | Buffer): AACTree;
8
+ processTexts(filePathOrBuffer: string | Buffer, translations: Map<string, string>, outputPath: string): Buffer;
9
+ saveFromTree(tree: AACTree, _outputPath: string): void;
10
+ /**
11
+ * Extract strings with metadata for aac-tools-platform compatibility
12
+ * Uses the generic implementation from BaseProcessor
13
+ */
14
+ extractStringsWithMetadata(filePath: string): Promise<ExtractStringsResult>;
15
+ /**
16
+ * Generate translated download for aac-tools-platform compatibility
17
+ * Uses the generic implementation from BaseProcessor
18
+ */
19
+ generateTranslatedDownload(filePath: string, translatedStrings: TranslatedString[], sourceStrings: SourceString[]): Promise<string>;
20
+ }
21
+ export { DotProcessor };
@@ -0,0 +1,191 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.DotProcessor = void 0;
7
+ const baseProcessor_1 = require("../core/baseProcessor");
8
+ const treeStructure_1 = require("../core/treeStructure");
9
+ // Removed unused import: FileProcessor
10
+ const fs_1 = __importDefault(require("fs"));
11
+ class DotProcessor extends baseProcessor_1.BaseProcessor {
12
+ constructor(options) {
13
+ super(options);
14
+ }
15
+ parseDotFile(content) {
16
+ const nodes = new Map();
17
+ const edges = [];
18
+ // Extract all edge statements using regex to handle single-line DOT files
19
+ const edgeRegex = /"?([^"\s]+)"?\s*->\s*"?([^"\s]+)"?(?:\s*\[label="([^"]+)"\])?/g;
20
+ const nodeRegex = /"?([^"\s]+)"?\s*\[label="([^"]+)"\]/g;
21
+ // Find all explicit node definitions
22
+ let nodeMatch;
23
+ while ((nodeMatch = nodeRegex.exec(content)) !== null) {
24
+ const [, id, label] = nodeMatch;
25
+ nodes.set(id, { id, label });
26
+ }
27
+ // Find all edge definitions
28
+ let edgeMatch;
29
+ while ((edgeMatch = edgeRegex.exec(content)) !== null) {
30
+ const [, from, to, label] = edgeMatch;
31
+ edges.push({ from, to, label });
32
+ // Add nodes if they don't exist (implicit definition)
33
+ if (!nodes.has(from)) {
34
+ nodes.set(from, { id: from, label: from });
35
+ }
36
+ if (!nodes.has(to)) {
37
+ nodes.set(to, { id: to, label: to });
38
+ }
39
+ }
40
+ return { nodes: Array.from(nodes.values()), edges };
41
+ }
42
+ extractTexts(filePathOrBuffer) {
43
+ const content = typeof filePathOrBuffer === 'string'
44
+ ? fs_1.default.readFileSync(filePathOrBuffer, 'utf8')
45
+ : filePathOrBuffer.toString('utf8');
46
+ const { nodes, edges } = this.parseDotFile(content);
47
+ const texts = [];
48
+ // Collect node labels
49
+ for (const node of nodes) {
50
+ texts.push(node.label);
51
+ }
52
+ // Collect edge labels
53
+ for (const edge of edges) {
54
+ if (edge.label) {
55
+ texts.push(edge.label);
56
+ }
57
+ }
58
+ return texts;
59
+ }
60
+ loadIntoTree(filePathOrBuffer) {
61
+ let content;
62
+ try {
63
+ content =
64
+ typeof filePathOrBuffer === 'string'
65
+ ? fs_1.default.readFileSync(filePathOrBuffer, 'utf8')
66
+ : filePathOrBuffer.toString('utf8');
67
+ }
68
+ catch (error) {
69
+ // Re-throw file system errors (like file not found)
70
+ if (typeof filePathOrBuffer === 'string') {
71
+ throw error;
72
+ }
73
+ // For buffer errors, return empty tree
74
+ return new treeStructure_1.AACTree();
75
+ }
76
+ // Check if content looks like text and is non-empty
77
+ if (!content || content.trim().length === 0) {
78
+ return new treeStructure_1.AACTree();
79
+ }
80
+ // Check for binary data (contains null bytes or non-printable characters) without control-regex
81
+ const head = content.substring(0, 100);
82
+ let hasControl = false;
83
+ for (let i = 0; i < head.length; i++) {
84
+ const code = head.charCodeAt(i);
85
+ if (code === 0 || (code >= 0 && code <= 8) || (code >= 14 && code <= 31) || code >= 127) {
86
+ hasControl = true;
87
+ break;
88
+ }
89
+ }
90
+ if (hasControl) {
91
+ return new treeStructure_1.AACTree();
92
+ }
93
+ const { nodes, edges } = this.parseDotFile(content);
94
+ const tree = new treeStructure_1.AACTree();
95
+ // Create pages for each node and add a self button representing the node label
96
+ for (const node of nodes) {
97
+ const page = new treeStructure_1.AACPage({
98
+ id: node.id,
99
+ name: node.label,
100
+ grid: [],
101
+ buttons: [],
102
+ parentId: null,
103
+ });
104
+ tree.addPage(page);
105
+ // Add a self button so single-node graphs yield one button
106
+ page.addButton(new treeStructure_1.AACButton({
107
+ id: `${node.id}_self`,
108
+ label: node.label,
109
+ message: node.label,
110
+ semanticAction: {
111
+ intent: treeStructure_1.AACSemanticIntent.SPEAK_TEXT,
112
+ text: node.label,
113
+ fallback: { type: 'SPEAK', message: node.label },
114
+ },
115
+ }));
116
+ }
117
+ // Create navigation buttons based on edges
118
+ for (const edge of edges) {
119
+ const fromPage = tree.getPage(edge.from);
120
+ if (fromPage) {
121
+ const button = new treeStructure_1.AACButton({
122
+ id: `nav_${edge.from}_${edge.to}`,
123
+ label: edge.label || edge.to,
124
+ message: '',
125
+ targetPageId: edge.to,
126
+ });
127
+ fromPage.addButton(button);
128
+ }
129
+ }
130
+ return tree;
131
+ }
132
+ processTexts(filePathOrBuffer, translations, outputPath) {
133
+ const safeBuffer = Buffer.isBuffer(filePathOrBuffer)
134
+ ? filePathOrBuffer
135
+ : fs_1.default.readFileSync(filePathOrBuffer);
136
+ const content = safeBuffer.toString('utf8');
137
+ let translatedContent = content;
138
+ translations.forEach((translation, text) => {
139
+ if (typeof text === 'string' && typeof translation === 'string') {
140
+ // Escape special regex characters in the text
141
+ const escapedText = text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
142
+ const escapedTranslation = translation.replace(/\$/g, '$$$$'); // Escape $ in replacement
143
+ translatedContent = translatedContent.replace(new RegExp(`label="${escapedText}"`, 'g'), `label="${escapedTranslation}"`);
144
+ }
145
+ });
146
+ const resultBuffer = Buffer.from(translatedContent || '', 'utf8');
147
+ // Save to output path
148
+ fs_1.default.writeFileSync(outputPath, resultBuffer);
149
+ return resultBuffer;
150
+ }
151
+ saveFromTree(tree, _outputPath) {
152
+ let dotContent = 'digraph AACBoard {\n';
153
+ // Add nodes
154
+ for (const pageId in tree.pages) {
155
+ const page = tree.pages[pageId];
156
+ dotContent += ` "${page.id}" [label="${page.name}"]\n`;
157
+ }
158
+ // Add edges from navigation buttons (semantic intent or legacy targetPageId)
159
+ for (const pageId in tree.pages) {
160
+ const page = tree.pages[pageId];
161
+ page.buttons
162
+ .filter((btn) => {
163
+ const intentStr = String(btn.semanticAction?.intent);
164
+ return (intentStr === 'NAVIGATE_TO' || !!btn.targetPageId || !!btn.semanticAction?.targetId);
165
+ })
166
+ .forEach((btn) => {
167
+ const target = btn.semanticAction?.targetId || btn.targetPageId;
168
+ if (target) {
169
+ dotContent += ` "${page.id}" -> "${target}" [label="${btn.label}"]\n`;
170
+ }
171
+ });
172
+ }
173
+ dotContent += '}\n';
174
+ fs_1.default.writeFileSync(_outputPath, dotContent);
175
+ }
176
+ /**
177
+ * Extract strings with metadata for aac-tools-platform compatibility
178
+ * Uses the generic implementation from BaseProcessor
179
+ */
180
+ async extractStringsWithMetadata(filePath) {
181
+ return this.extractStringsWithMetadataGeneric(filePath);
182
+ }
183
+ /**
184
+ * Generate translated download for aac-tools-platform compatibility
185
+ * Uses the generic implementation from BaseProcessor
186
+ */
187
+ async generateTranslatedDownload(filePath, translatedStrings, sourceStrings) {
188
+ return this.generateTranslatedDownloadGeneric(filePath, translatedStrings, sourceStrings);
189
+ }
190
+ }
191
+ exports.DotProcessor = DotProcessor;
@@ -0,0 +1,145 @@
1
+ import { BaseProcessor, ExtractStringsResult, TranslatedString, SourceString } from '../core/baseProcessor';
2
+ import { AACTree } from '../core/treeStructure';
3
+ /**
4
+ * Excel Processor for converting AAC grids to Excel format
5
+ * Converts AAC tree structures to Excel workbooks with each page as a worksheet
6
+ * Supports visual styling, navigation links, and vocabulary analysis workflows
7
+ */
8
+ export declare class ExcelProcessor extends BaseProcessor {
9
+ private static readonly NAVIGATION_BUTTONS;
10
+ /**
11
+ * Extract all text content from an Excel file
12
+ * @param filePathOrBuffer - Path to Excel file or Buffer containing Excel data
13
+ * @returns Array of all text content found in the Excel file
14
+ */
15
+ extractTexts(filePathOrBuffer: string | Buffer): string[];
16
+ /**
17
+ * Load Excel file into AACTree structure
18
+ * @param filePathOrBuffer - Path to Excel file or Buffer containing Excel data
19
+ * @returns AACTree representation of the Excel file
20
+ */
21
+ loadIntoTree(filePathOrBuffer: string | Buffer): AACTree;
22
+ /**
23
+ * Process texts in Excel file (apply translations)
24
+ * @param filePathOrBuffer - Path to Excel file or Buffer containing Excel data
25
+ * @param translations - Map of original text to translated text
26
+ * @param outputPath - Path where translated Excel file should be saved
27
+ * @returns Buffer containing the translated Excel file
28
+ */
29
+ processTexts(filePathOrBuffer: string | Buffer, translations: Map<string, string>, outputPath: string): Buffer;
30
+ /**
31
+ * Convert an AAC page to an Excel worksheet
32
+ * @param workbook - Excel workbook to add worksheet to
33
+ * @param page - AAC page to convert
34
+ * @param tree - Full AAC tree for navigation context
35
+ * @param usedNames - Set of already used worksheet names to avoid duplicates
36
+ */
37
+ private convertPageToWorksheet;
38
+ /**
39
+ * Calculate optimal grid dimensions for buttons
40
+ * @param page - AAC page to analyze
41
+ * @returns Object with rows and cols dimensions
42
+ */
43
+ private calculateGridDimensions;
44
+ /**
45
+ * Convert grid layout to Excel cells
46
+ * @param worksheet - Excel worksheet
47
+ * @param grid - 2D array of AAC buttons
48
+ * @param startRow - Starting row number
49
+ */
50
+ private convertGridLayout;
51
+ /**
52
+ * Convert button list to grid layout in Excel
53
+ * @param worksheet - Excel worksheet
54
+ * @param buttons - Array of AAC buttons
55
+ * @param rows - Number of rows in grid
56
+ * @param cols - Number of columns in grid
57
+ * @param startRow - Starting row number
58
+ */
59
+ private convertButtonsToGrid;
60
+ /**
61
+ * Set button data and formatting for an Excel cell
62
+ * @param worksheet - Excel worksheet
63
+ * @param button - AAC button to represent
64
+ * @param row - Excel row number
65
+ * @param col - Excel column number
66
+ */
67
+ private setButtonCell;
68
+ /**
69
+ * Apply AAC button styling to Excel cell
70
+ * @param cell - Excel cell to style
71
+ * @param style - AAC style object
72
+ */
73
+ private applyCellStyling;
74
+ /**
75
+ * Convert color string to ARGB format for Excel
76
+ * @param color - Color string (hex, rgb, etc.)
77
+ * @returns ARGB color string
78
+ */
79
+ private convertColorToArgb;
80
+ /**
81
+ * Add navigation link to cell for worksheet navigation
82
+ * @param cell - Excel cell to add link to
83
+ * @param targetPageId - Target page ID to link to
84
+ */
85
+ private addNavigationLink;
86
+ /**
87
+ * Set appropriate cell size for button representation
88
+ * @param worksheet - Excel worksheet
89
+ * @param row - Row number
90
+ * @param col - Column number
91
+ */
92
+ private setCellSize;
93
+ /**
94
+ * Add navigation row with standard AAC navigation buttons
95
+ * @param worksheet - Excel worksheet
96
+ * @param page - Current AAC page
97
+ * @param tree - Full AAC tree for navigation context
98
+ */
99
+ private addNavigationRow;
100
+ /**
101
+ * Apply general formatting to the worksheet
102
+ * @param worksheet - Excel worksheet
103
+ * @param rows - Number of content rows
104
+ * @param cols - Number of content columns
105
+ * @param startRow - Starting row for content
106
+ */
107
+ private formatWorksheet;
108
+ /**
109
+ * Sanitize worksheet name for Excel compatibility
110
+ * @param name - Original name
111
+ * @returns Sanitized name safe for Excel worksheet
112
+ */
113
+ private sanitizeWorksheetName;
114
+ /**
115
+ * Get a unique worksheet name by appending a number if needed
116
+ * @param name - Original name
117
+ * @param usedNames - Set of already used names (case-insensitive)
118
+ * @returns Unique worksheet name
119
+ */
120
+ private getUniqueWorksheetName;
121
+ /**
122
+ * Check if navigation row should be added (configurable feature)
123
+ * @returns True if navigation row should be added
124
+ */
125
+ private shouldAddNavigationRow;
126
+ /**
127
+ * Override saveFromTree to handle async nature of Excel operations
128
+ * Note: This method is async but maintains the sync interface for compatibility
129
+ */
130
+ saveFromTree(tree: AACTree, outputPath: string): Promise<void>;
131
+ /**
132
+ * Async version of saveFromTree for internal use
133
+ */
134
+ private saveFromTreeAsync;
135
+ /**
136
+ * Extract strings with metadata for aac-tools-platform compatibility
137
+ * Uses the generic implementation from BaseProcessor
138
+ */
139
+ extractStringsWithMetadata(filePath: string): Promise<ExtractStringsResult>;
140
+ /**
141
+ * Generate translated download for aac-tools-platform compatibility
142
+ * Uses the generic implementation from BaseProcessor
143
+ */
144
+ generateTranslatedDownload(filePath: string, translatedStrings: TranslatedString[], sourceStrings: SourceString[]): Promise<string>;
145
+ }