@willwade/aac-processors 0.2.19 → 0.3.0

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 (37) hide show
  1. package/README.md +1 -0
  2. package/dist/browser/core/treeStructure.js +17 -0
  3. package/dist/browser/index.browser.js +17 -1
  4. package/dist/browser/processors/gotalkNow/nsKeyed.js +101 -0
  5. package/dist/browser/processors/gotalkNowProcessor.js +463 -0
  6. package/dist/browser/processors/gridset/cellHelpers.js +13 -3
  7. package/dist/browser/processors/gridset/commands.js +771 -0
  8. package/dist/browser/processors/gridset/pluginTypes.js +19 -1
  9. package/dist/browser/processors/gridsetProcessor.js +874 -17
  10. package/dist/browser/processors/obfProcessor.js +6 -2
  11. package/dist/browser/validation/gridsetValidator.js +54 -198
  12. package/dist/cli/index.js +3 -0
  13. package/dist/core/analyze.js +5 -0
  14. package/dist/core/treeStructure.d.ts +20 -0
  15. package/dist/core/treeStructure.js +17 -0
  16. package/dist/gotalkNow.d.ts +6 -0
  17. package/dist/gotalkNow.js +11 -0
  18. package/dist/index.browser.d.ts +1 -0
  19. package/dist/index.browser.js +19 -2
  20. package/dist/index.node.d.ts +1 -0
  21. package/dist/index.node.js +6 -1
  22. package/dist/processors/gotalkNow/nsKeyed.d.ts +27 -0
  23. package/dist/processors/gotalkNow/nsKeyed.js +105 -0
  24. package/dist/processors/gotalkNowProcessor.d.ts +51 -0
  25. package/dist/processors/gotalkNowProcessor.js +469 -0
  26. package/dist/processors/gridset/cellHelpers.js +13 -3
  27. package/dist/processors/gridset/commands.d.ts +2 -0
  28. package/dist/processors/gridset/commands.js +771 -0
  29. package/dist/processors/gridset/pluginTypes.d.ts +7 -0
  30. package/dist/processors/gridset/pluginTypes.js +19 -1
  31. package/dist/processors/gridsetProcessor.js +874 -17
  32. package/dist/processors/index.d.ts +1 -0
  33. package/dist/processors/index.js +3 -1
  34. package/dist/processors/obfProcessor.js +6 -2
  35. package/dist/validation/gridsetValidator.d.ts +8 -15
  36. package/dist/validation/gridsetValidator.js +54 -198
  37. package/package.json +5 -1
@@ -688,7 +688,9 @@ class ObfProcessor extends BaseProcessor {
688
688
  });
689
689
  const manifest = {
690
690
  format: OBF_FORMAT_VERSION,
691
- root: tree.metadata.defaultHomePageId,
691
+ root: tree.metadata.defaultHomePageId
692
+ ? this.getPageFilename(tree.metadata.defaultHomePageId, tree.metadata)
693
+ : undefined,
692
694
  paths: {
693
695
  boards: Object.fromEntries(Object.entries(tree.pages).map(([id, page]) => [
694
696
  id,
@@ -755,7 +757,9 @@ class ObfProcessor extends BaseProcessor {
755
757
  if (Object.keys(tree.pages).length > 0) {
756
758
  const manifest = {
757
759
  format: OBF_FORMAT_VERSION,
758
- root: tree.metadata.defaultHomePageId,
760
+ root: tree.metadata.defaultHomePageId
761
+ ? this.getPageFilename(tree.metadata.defaultHomePageId, tree.metadata)
762
+ : undefined,
759
763
  paths: {
760
764
  boards: Object.fromEntries(Object.entries(tree.pages).map(([id, page]) => [
761
765
  id,
@@ -29,12 +29,12 @@ export class GridsetValidator extends BaseValidator {
29
29
  if (name.endsWith('.gridset') || name.endsWith('.gridsetx')) {
30
30
  return true;
31
31
  }
32
- // Try to parse as XML and check for gridset structure
32
+ // Try to parse as XML and check for a Grid 3 <Grid> root element
33
33
  try {
34
34
  const contentStr = typeof content === 'string' ? content : decodeText(toUint8Array(content));
35
35
  const parser = new xml2js.Parser();
36
36
  const result = await parser.parseStringPromise(contentStr);
37
- return result && (result.gridset || result.Gridset);
37
+ return !!(result && (result.Grid || result.grid));
38
38
  }
39
39
  catch {
40
40
  return false;
@@ -78,7 +78,7 @@ export class GridsetValidator extends BaseValidator {
78
78
  return content[0] === 0x50 && content[1] === 0x4b && content[2] === 0x03 && content[3] === 0x04;
79
79
  }
80
80
  /**
81
- * Validate a single XML file (legacy or exploded format)
81
+ * Validate a single grid.xml file (exploded/non-zip format)
82
82
  */
83
83
  async validateSingleXml(content, filename, _filesize) {
84
84
  let xmlObj = null;
@@ -94,49 +94,57 @@ export class GridsetValidator extends BaseValidator {
94
94
  });
95
95
  if (!xmlObj)
96
96
  return;
97
- await this.add_check('xml_structure', 'gridset root element', async () => {
98
- if (!xmlObj.gridset && !xmlObj.Gridset) {
99
- this.err('missing root gridset element', true);
97
+ await this.add_check('xml_structure', 'Grid root element', async () => {
98
+ if (!xmlObj.Grid && !xmlObj.grid) {
99
+ this.err('missing root Grid element', true);
100
100
  }
101
101
  });
102
- const gridset = xmlObj.gridset || xmlObj.Gridset;
103
- if (gridset) {
104
- await this.validateGridsetStructure(gridset, filename, content);
102
+ const grid = xmlObj.Grid || xmlObj.grid;
103
+ if (grid) {
104
+ await this.validateGridStructure(grid, filename);
105
105
  }
106
106
  }
107
107
  /**
108
108
  * Validate a ZIP archive (.gridset)
109
+ *
110
+ * Real Grid 3 archives do NOT contain a top-level gridset.xml. The required
111
+ * structure is: Settings0/settings.xml + FileMap.xml + Grids/<name>/grid.xml
112
+ * (+ optional Styles, images, thumbnails).
109
113
  */
110
- async validateZipArchive(content, filename, _filesize) {
114
+ async validateZipArchive(content, _filename, _filesize) {
111
115
  const zip = await this._options.zipAdapter(content);
112
116
  const entries = zip.listFiles();
113
- // Check for gridset.xml (required)
114
- await this.add_check('gridset_xml_presence', 'gridset.xml presence', async () => {
115
- const gridsetEntry = entries.find((e) => e.toLowerCase() === 'gridset.xml');
116
- if (!gridsetEntry) {
117
- this.err('Missing gridset.xml in archive', true);
117
+ // --- Required: at least one Grids/<name>/grid.xml ---
118
+ const gridEntries = entries.filter((e) => /^Grids\/.+\/grid\.xml$/i.test(e));
119
+ await this.add_check('grid_xml_presence', 'Grids/*/grid.xml presence', async () => {
120
+ if (gridEntries.length === 0) {
121
+ this.err('No Grids/<name>/grid.xml found in archive', true);
118
122
  }
119
- else {
123
+ });
124
+ // Validate the <Grid> structure of each grid.xml (sample up to 5)
125
+ for (let i = 0; i < Math.min(gridEntries.length, 5); i++) {
126
+ const entry = gridEntries[i];
127
+ await this.add_check(`grid_xml[${entry}]`, `grid structure: ${entry}`, async () => {
120
128
  try {
121
- const gridsetXml = await zip.readFile(gridsetEntry);
129
+ const gridXml = await zip.readFile(entry);
122
130
  const parser = new xml2js.Parser();
123
- const xmlObj = await parser.parseStringPromise(gridsetXml);
124
- const gridset = xmlObj.gridset || xmlObj.Gridset;
125
- if (!gridset) {
126
- this.err('Invalid gridset.xml structure', true);
131
+ const xmlObj = await parser.parseStringPromise(gridXml);
132
+ const grid = xmlObj.Grid || xmlObj.grid;
133
+ if (!grid) {
134
+ this.err(`${entry}: missing root <Grid> element`);
127
135
  }
128
136
  else {
129
- await this.validateGridsetStructure(gridset, filename, new Uint8Array());
137
+ await this.validateGridStructure(grid, entry);
130
138
  }
131
139
  }
132
140
  catch (e) {
133
- this.err(`Failed to parse gridset.xml: ${e.message}`, true);
141
+ this.err(`${entry}: failed to parse XML: ${e.message}`);
134
142
  }
135
- }
136
- });
137
- // Check for settings.xml (highly recommended/required for metadata)
143
+ });
144
+ }
145
+ // --- Recommended: Settings0/settings.xml ---
138
146
  await this.add_check('settings_xml_presence', 'settings.xml presence', async () => {
139
- const settingsEntry = entries.find((e) => e.toLowerCase() === 'settings.xml');
147
+ const settingsEntry = entries.find((e) => e.toLowerCase() === 'settings.xml' || e.toLowerCase().endsWith('/settings.xml'));
140
148
  if (!settingsEntry) {
141
149
  this.warn('Missing settings.xml in archive (required for full metadata)');
142
150
  }
@@ -161,187 +169,35 @@ export class GridsetValidator extends BaseValidator {
161
169
  }
162
170
  }
163
171
  });
164
- }
165
- /**
166
- * Validate Gridset structure
167
- */
168
- async validateGridsetStructure(gridset, _filename, _content) {
169
- // Check for required elements
170
- await this.add_check('gridset_id', 'gridset id', async () => {
171
- const id = gridset.$.id || gridset.$.Id;
172
- if (!id) {
173
- this.warn('gridset should have an id attribute');
174
- }
175
- });
176
- await this.add_check('gridset_name', 'gridset name', async () => {
177
- const name = gridset.$.name || gridset.$.Name || gridset.name?.[0];
178
- if (!name) {
179
- this.warn('gridset should have a name attribute or element');
180
- }
181
- });
182
- // Check for pages
183
- await this.add_check('pages', 'pages element', async () => {
184
- if (!gridset.pages && !gridset.Pages) {
185
- this.err('gridset must have a pages element');
186
- }
187
- else {
188
- const pages = gridset.pages || gridset.Pages;
189
- if (!pages[0] || !Array.isArray(pages[0].page)) {
190
- this.warn('pages should contain at least one page element');
191
- }
192
- }
193
- });
194
- // Validate individual pages
195
- const pages = gridset.pages?.[0] || gridset.Pages?.[0];
196
- if (pages && Array.isArray(pages.page)) {
197
- await this.add_check('page_count', 'page count', async () => {
198
- if (pages.page.length === 0) {
199
- this.err('gridset must contain at least one page');
200
- }
201
- });
202
- for (let i = 0; i < Math.min(pages.page.length, 10); i++) {
203
- // Limit to first 10 pages to avoid excessive validation
204
- const page = pages.page[i];
205
- await this.validatePage(page, i);
206
- }
207
- }
208
- // Check for fixedCellSize
209
- await this.add_check('fixed_cell_size', 'fixedCellSize element', async () => {
210
- const fixedSize = gridset.fixedCellSize || gridset.FixedCellSize;
211
- if (!fixedSize) {
212
- this.warn('gridset should have a fixedCellSize element for consistency');
213
- }
214
- else {
215
- // Validate fixedCellSize structure
216
- const size = fixedSize[0];
217
- if (size) {
218
- const width = size.$.width || size.$.Width;
219
- const height = size.$.height || size.$.Height;
220
- if (!width || !height) {
221
- this.warn('fixedCellSize should have both width and height attributes');
222
- }
223
- else if (isNaN(parseInt(width)) || isNaN(parseInt(height))) {
224
- this.err('fixedCellSize width and height must be valid numbers');
225
- }
226
- }
227
- }
228
- });
229
- // Check for styles
230
- await this.add_check('styles', 'styles element', async () => {
231
- const styles = gridset.styles || gridset.Styles;
232
- if (!styles) {
233
- this.warn('gridset should have a styles element for consistent formatting');
172
+ // --- Recommended: FileMap.xml (used for image resolution) ---
173
+ await this.add_check('filemap_presence', 'FileMap.xml presence', async () => {
174
+ const filemapEntry = entries.find((e) => e.toLowerCase() === 'filemap.xml');
175
+ if (!filemapEntry) {
176
+ this.warn('Missing FileMap.xml in archive (used for image resolution)');
234
177
  }
235
178
  });
236
179
  }
237
180
  /**
238
- * Validate a single page
181
+ * Validate a real Grid 3 <Grid> element (from grid.xml).
182
+ * Checks for GridGuid, Cells, and basic cell structure.
239
183
  */
240
- async validatePage(page, index) {
241
- await this.add_check(`page[${index}]_id`, `page ${index} id`, async () => {
242
- const id = page.$.id || page.$.Id;
243
- if (!id) {
244
- this.err(`page at index ${index} is missing id attribute`);
184
+ async validateGridStructure(grid, label) {
185
+ await this.add_check(`${label}_gridguid`, 'GridGuid', async () => {
186
+ const guid = grid.GridGuid || grid.gridGuid;
187
+ if (!guid) {
188
+ this.warn(`${label}: missing <GridGuid> element`);
245
189
  }
246
190
  });
247
- await this.add_check(`page[${index}]_name`, `page ${index} name`, async () => {
248
- const name = page.$.name || page.$.Name || page.name?.[0];
249
- if (!name) {
250
- this.warn(`page ${index} should have a name`);
251
- }
252
- });
253
- // Check for cells
254
- await this.add_check(`page[${index}]_cells`, `page ${index} cells`, async () => {
255
- const cells = page.cells || page.Cells;
191
+ await this.add_check(`${label}_cells`, 'Cells element', async () => {
192
+ const cells = grid.Cells || grid.cells;
256
193
  if (!cells) {
257
- this.warn(`page ${index} should have a cells element`);
194
+ this.warn(`${label}: missing <Cells> element`);
195
+ return;
258
196
  }
259
- else {
260
- const cellArray = cells[0]?.cell || cells[0]?.Cell;
261
- if (!cellArray || !Array.isArray(cellArray) || cellArray.length === 0) {
262
- this.warn(`page ${index} should contain at least one cell`);
263
- }
197
+ const cellArray = cells[0]?.Cell || cells[0]?.cell;
198
+ if (!cellArray || !Array.isArray(cellArray) || cellArray.length === 0) {
199
+ this.warn(`${label}: <Cells> should contain at least one <Cell>`);
264
200
  }
265
201
  });
266
- // Validate cells if present
267
- const cells = page.cells?.[0] || page.Cells?.[0];
268
- if (cells) {
269
- const cellArray = cells.cell || cells.Cell;
270
- if (Array.isArray(cellArray) && cellArray.length > 0) {
271
- // Sample a few cells to validate
272
- const sampleSize = Math.min(cellArray.length, 5);
273
- for (let i = 0; i < sampleSize; i++) {
274
- await this.validateCell(cellArray[i], index, i);
275
- }
276
- }
277
- }
278
- }
279
- /**
280
- * Validate a single cell
281
- */
282
- async validateCell(cell, pageIdx, cellIdx) {
283
- await this.add_check(`page[${pageIdx}]_cell[${cellIdx}]_id`, `cell id`, async () => {
284
- const id = cell.$.id || cell.$.Id;
285
- if (!id) {
286
- this.warn(`cell ${cellIdx} on page ${pageIdx} is missing id attribute`);
287
- }
288
- });
289
- await this.add_check(`page[${pageIdx}]_cell[${cellIdx}]_content`, `cell content`, async () => {
290
- const label = cell.$.label || cell.$.Label;
291
- const image = cell.$.image || cell.$.Image;
292
- if (!label && !image) {
293
- this.warn(`cell ${cellIdx} on page ${pageIdx} should have a label or image`);
294
- }
295
- });
296
- // Validate scan block number (Grid 3 attribute)
297
- await this.add_check(`page[${pageIdx}]_cell[${cellIdx}]_scanblock`, `cell scan block`, async () => {
298
- const scanBlock = cell.$.scanBlock || cell.$.ScanBlock;
299
- if (scanBlock !== undefined) {
300
- const blockNum = parseInt(scanBlock, 10);
301
- if (isNaN(blockNum) || blockNum < 1 || blockNum > 8) {
302
- this.err(`cell ${cellIdx} on page ${pageIdx} has invalid scanBlock value: ${scanBlock} (must be 1-8)`, false);
303
- }
304
- }
305
- });
306
- // Check for color attributes
307
- const backgroundColor = cell.$.backgroundColor || cell.$.BackgroundColor;
308
- const _color = cell.$.color || cell.$.Color;
309
- if (backgroundColor) {
310
- await this.add_check(`page[${pageIdx}]_cell[${cellIdx}]_bg_color`, `cell background color`, async () => {
311
- // Grid3 colors can be in various formats: named colors, hex, ARGB
312
- // We just check it's not empty
313
- if (backgroundColor.length === 0) {
314
- this.warn(`cell ${cellIdx} has empty background color`);
315
- }
316
- });
317
- }
318
- // Check for valid jump references
319
- const jump = cell.$.jump || cell.$.Jump;
320
- if (jump) {
321
- await this.add_check(`page[${pageIdx}]_cell[${cellIdx}]_jump`, `cell jump reference`, async () => {
322
- if (typeof jump !== 'string' || jump.length === 0) {
323
- this.warn(`cell ${cellIdx} has invalid jump reference`);
324
- }
325
- });
326
- }
327
- }
328
- /**
329
- * Validate color format (Grid3 uses ARGB format)
330
- */
331
- isValidGrid3Color(color) {
332
- if (!color || color.length === 0)
333
- return false;
334
- // Named colors are valid
335
- if (/^[a-zA-Z]+$/.test(color))
336
- return true;
337
- // ARGB format: #AARRGGBB or #RRGGBB
338
- if (color.startsWith('#')) {
339
- return color.length === 7 || color.length === 9;
340
- }
341
- // RGB format: rgb(r,g,b) or rgba(r,g,b,a)
342
- if (color.startsWith('rgb')) {
343
- return true; // Simplified check
344
- }
345
- return false;
346
202
  }
347
203
  }
package/dist/cli/index.js CHANGED
@@ -25,6 +25,9 @@ async function detectFormat(filePath) {
25
25
  if (filePath.endsWith('.gridset')) {
26
26
  return 'gridset';
27
27
  }
28
+ if (filePath.endsWith('.gtbz')) {
29
+ return 'gotalknow';
30
+ }
28
31
  // Otherwise use file extension
29
32
  return (0, io_1.extname)(filePath).slice(1);
30
33
  }
@@ -11,6 +11,7 @@ const snapProcessor_1 = require("../processors/snapProcessor");
11
11
  const dotProcessor_1 = require("../processors/dotProcessor");
12
12
  const excelProcessor_1 = require("../processors/excelProcessor");
13
13
  const applePanelsProcessor_1 = require("../processors/applePanelsProcessor");
14
+ const gotalkNowProcessor_1 = require("../processors/gotalkNowProcessor");
14
15
  /**
15
16
  * Resolve a processor instance by friendly format name or common extension.
16
17
  * @param format Format key or extension (e.g., 'snap', 'obf', 'xlsx')
@@ -45,6 +46,10 @@ function getProcessor(format, options) {
45
46
  case 'panels': // Apple Panels file extension
46
47
  case 'ascconfig': // Apple Panels folder format
47
48
  return new applePanelsProcessor_1.ApplePanelsProcessor(options);
49
+ case 'gotalknow':
50
+ case 'gotalk':
51
+ case 'gtbz': // GoTalk NOW file extension
52
+ return new gotalkNowProcessor_1.GotalkNowProcessor(options);
48
53
  default:
49
54
  throw new Error('Unknown format: ' + format);
50
55
  }
@@ -22,10 +22,25 @@ export declare enum AACSemanticIntent {
22
22
  CLEAR_TEXT = "CLEAR_TEXT",
23
23
  COPY_TEXT = "COPY_TEXT",
24
24
  PASTE_TEXT = "PASTE_TEXT",
25
+ SELECT_ALL = "SELECT_ALL",
26
+ CURSOR_MOVE = "CURSOR_MOVE",
27
+ UNDO = "UNDO",
28
+ PRINT = "PRINT",
25
29
  SEND_KEYS = "SEND_KEYS",
26
30
  MOUSE_CLICK = "MOUSE_CLICK",
31
+ DEVICE_MUTE = "DEVICE_MUTE",
32
+ TOGGLE_STATE = "TOGGLE_STATE",
33
+ WEB_NAVIGATE = "WEB_NAVIGATE",
34
+ WEB_SCROLL = "WEB_SCROLL",
35
+ WEB_FOCUS_ELEMENT = "WEB_FOCUS_ELEMENT",
36
+ WEB_ACTIVATE_ELEMENT = "WEB_ACTIVATE_ELEMENT",
37
+ WEB_EXECUTE_SCRIPT = "WEB_EXECUTE_SCRIPT",
27
38
  PLAY_SOUND = "PLAY_SOUND",
28
39
  PLAY_VIDEO = "PLAY_VIDEO",
40
+ STOP_MEDIA = "STOP_MEDIA",
41
+ TAKE_PHOTO = "TAKE_PHOTO",
42
+ WAIT = "WAIT",
43
+ REPEAT_COMMANDS = "REPEAT_COMMANDS",
29
44
  SCAN_NEXT = "SCAN_NEXT",
30
45
  SCAN_SELECT = "SCAN_SELECT",
31
46
  PLATFORM_SPECIFIC = "PLATFORM_SPECIFIC"
@@ -99,6 +114,11 @@ export interface AACSemanticAction {
99
114
  [key: string]: any;
100
115
  };
101
116
  };
117
+ gotalkNow?: {
118
+ buttonType: string;
119
+ jumpTo?: number;
120
+ audioLocation?: string;
121
+ };
102
122
  };
103
123
  fallback?: {
104
124
  type: 'SPEAK' | 'NAVIGATE' | 'ACTION';
@@ -30,12 +30,29 @@ var AACSemanticIntent;
30
30
  AACSemanticIntent["CLEAR_TEXT"] = "CLEAR_TEXT";
31
31
  AACSemanticIntent["COPY_TEXT"] = "COPY_TEXT";
32
32
  AACSemanticIntent["PASTE_TEXT"] = "PASTE_TEXT";
33
+ AACSemanticIntent["SELECT_ALL"] = "SELECT_ALL";
34
+ AACSemanticIntent["CURSOR_MOVE"] = "CURSOR_MOVE";
35
+ AACSemanticIntent["UNDO"] = "UNDO";
36
+ AACSemanticIntent["PRINT"] = "PRINT";
33
37
  // System Control
34
38
  AACSemanticIntent["SEND_KEYS"] = "SEND_KEYS";
35
39
  AACSemanticIntent["MOUSE_CLICK"] = "MOUSE_CLICK";
40
+ AACSemanticIntent["DEVICE_MUTE"] = "DEVICE_MUTE";
41
+ AACSemanticIntent["TOGGLE_STATE"] = "TOGGLE_STATE";
42
+ // Web Control
43
+ AACSemanticIntent["WEB_NAVIGATE"] = "WEB_NAVIGATE";
44
+ AACSemanticIntent["WEB_SCROLL"] = "WEB_SCROLL";
45
+ AACSemanticIntent["WEB_FOCUS_ELEMENT"] = "WEB_FOCUS_ELEMENT";
46
+ AACSemanticIntent["WEB_ACTIVATE_ELEMENT"] = "WEB_ACTIVATE_ELEMENT";
47
+ AACSemanticIntent["WEB_EXECUTE_SCRIPT"] = "WEB_EXECUTE_SCRIPT";
36
48
  // Media
37
49
  AACSemanticIntent["PLAY_SOUND"] = "PLAY_SOUND";
38
50
  AACSemanticIntent["PLAY_VIDEO"] = "PLAY_VIDEO";
51
+ AACSemanticIntent["STOP_MEDIA"] = "STOP_MEDIA";
52
+ AACSemanticIntent["TAKE_PHOTO"] = "TAKE_PHOTO";
53
+ // Command Execution
54
+ AACSemanticIntent["WAIT"] = "WAIT";
55
+ AACSemanticIntent["REPEAT_COMMANDS"] = "REPEAT_COMMANDS";
39
56
  // Accessibility
40
57
  AACSemanticIntent["SCAN_NEXT"] = "SCAN_NEXT";
41
58
  AACSemanticIntent["SCAN_SELECT"] = "SCAN_SELECT";
@@ -0,0 +1,6 @@
1
+ /**
2
+ * GoTalk NOW Namespace
3
+ *
4
+ * GoTalk NOW (Attainment Company) format processing utilities.
5
+ */
6
+ export { GotalkNowProcessor } from './processors/gotalkNowProcessor';
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ /**
3
+ * GoTalk NOW Namespace
4
+ *
5
+ * GoTalk NOW (Attainment Company) format processing utilities.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.GotalkNowProcessor = void 0;
9
+ // Processor class
10
+ var gotalkNowProcessor_1 = require("./processors/gotalkNowProcessor");
11
+ Object.defineProperty(exports, "GotalkNowProcessor", { enumerable: true, get: function () { return gotalkNowProcessor_1.GotalkNowProcessor; } });
@@ -22,6 +22,7 @@ export { SnapProcessor } from './processors/snapProcessor';
22
22
  export { TouchChatProcessor } from './processors/touchchatProcessor';
23
23
  export { ApplePanelsProcessor } from './processors/applePanelsProcessor';
24
24
  export { AstericsGridProcessor } from './processors/astericsGridProcessor';
25
+ export { GotalkNowProcessor } from './processors/gotalkNowProcessor';
25
26
  export * as Metrics from './metrics';
26
27
  import { BaseProcessor, ProcessorOptions } from './core/baseProcessor';
27
28
  export { configureSqlJs } from './utils/sqlite';
@@ -39,7 +39,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
39
39
  return result;
40
40
  };
41
41
  Object.defineProperty(exports, "__esModule", { value: true });
42
- exports.configureSqlJs = exports.Metrics = exports.AstericsGridProcessor = exports.ApplePanelsProcessor = exports.TouchChatProcessor = exports.SnapProcessor = exports.GridsetProcessor = exports.ObfProcessor = exports.OpmlProcessor = exports.DotProcessor = void 0;
42
+ exports.configureSqlJs = exports.Metrics = exports.GotalkNowProcessor = exports.AstericsGridProcessor = exports.ApplePanelsProcessor = exports.TouchChatProcessor = exports.SnapProcessor = exports.GridsetProcessor = exports.ObfProcessor = exports.OpmlProcessor = exports.DotProcessor = void 0;
43
43
  exports.getProcessor = getProcessor;
44
44
  exports.getSupportedExtensions = getSupportedExtensions;
45
45
  exports.isExtensionSupported = isExtensionSupported;
@@ -68,6 +68,8 @@ var applePanelsProcessor_1 = require("./processors/applePanelsProcessor");
68
68
  Object.defineProperty(exports, "ApplePanelsProcessor", { enumerable: true, get: function () { return applePanelsProcessor_1.ApplePanelsProcessor; } });
69
69
  var astericsGridProcessor_1 = require("./processors/astericsGridProcessor");
70
70
  Object.defineProperty(exports, "AstericsGridProcessor", { enumerable: true, get: function () { return astericsGridProcessor_1.AstericsGridProcessor; } });
71
+ var gotalkNowProcessor_1 = require("./processors/gotalkNowProcessor");
72
+ Object.defineProperty(exports, "GotalkNowProcessor", { enumerable: true, get: function () { return gotalkNowProcessor_1.GotalkNowProcessor; } });
71
73
  // ===================================================================
72
74
  // UTILITY FUNCTIONS
73
75
  // ===================================================================
@@ -81,6 +83,7 @@ const snapProcessor_2 = require("./processors/snapProcessor");
81
83
  const touchchatProcessor_2 = require("./processors/touchchatProcessor");
82
84
  const applePanelsProcessor_2 = require("./processors/applePanelsProcessor");
83
85
  const astericsGridProcessor_2 = require("./processors/astericsGridProcessor");
86
+ const gotalkNowProcessor_2 = require("./processors/gotalkNowProcessor");
84
87
  var sqlite_1 = require("./utils/sqlite");
85
88
  Object.defineProperty(exports, "configureSqlJs", { enumerable: true, get: function () { return sqlite_1.configureSqlJs; } });
86
89
  /**
@@ -112,6 +115,8 @@ function getProcessor(filePathOrExtension, options) {
112
115
  return new applePanelsProcessor_2.ApplePanelsProcessor(options);
113
116
  case '.grd':
114
117
  return new astericsGridProcessor_2.AstericsGridProcessor(options);
118
+ case '.gtbz':
119
+ return new gotalkNowProcessor_2.GotalkNowProcessor(options);
115
120
  default:
116
121
  throw new Error(`Unsupported file extension: ${extension}`);
117
122
  }
@@ -121,7 +126,19 @@ function getProcessor(filePathOrExtension, options) {
121
126
  * @returns Array of supported file extensions
122
127
  */
123
128
  function getSupportedExtensions() {
124
- return ['.dot', '.opml', '.obf', '.obz', '.gridset', '.spb', '.sps', '.ce', '.plist', '.grd'];
129
+ return [
130
+ '.dot',
131
+ '.opml',
132
+ '.obf',
133
+ '.obz',
134
+ '.gridset',
135
+ '.spb',
136
+ '.sps',
137
+ '.ce',
138
+ '.plist',
139
+ '.grd',
140
+ '.gtbz',
141
+ ];
125
142
  }
126
143
  /**
127
144
  * Check if a file extension is supported
@@ -25,6 +25,7 @@ export * as Excel from './excel';
25
25
  export * as Opml from './opml';
26
26
  export * as ApplePanels from './applePanels';
27
27
  export * as AstericsGrid from './astericsGrid';
28
+ export * as GotalkNow from './gotalkNow';
28
29
  export * as Translation from './translation';
29
30
  import { BaseProcessor, ProcessorOptions } from './core/baseProcessor';
30
31
  /**
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
33
33
  return result;
34
34
  };
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.Translation = exports.AstericsGrid = exports.ApplePanels = exports.Opml = exports.Excel = exports.Dot = exports.TouchChat = exports.Obfset = exports.OBF = exports.Snap = exports.Gridset = exports.WordFormGenerator = exports.TDSnapLexiconParser = exports.Grid3VerbsParser = exports.Metrics = exports.Validation = exports.Analytics = void 0;
36
+ exports.Translation = exports.GotalkNow = exports.AstericsGrid = exports.ApplePanels = exports.Opml = exports.Excel = exports.Dot = exports.TouchChat = exports.Obfset = exports.OBF = exports.Snap = exports.Gridset = exports.WordFormGenerator = exports.TDSnapLexiconParser = exports.Grid3VerbsParser = exports.Metrics = exports.Validation = exports.Analytics = void 0;
37
37
  exports.getProcessor = getProcessor;
38
38
  exports.getSupportedExtensions = getSupportedExtensions;
39
39
  exports.isExtensionSupported = isExtensionSupported;
@@ -74,6 +74,7 @@ exports.Excel = __importStar(require("./excel"));
74
74
  exports.Opml = __importStar(require("./opml"));
75
75
  exports.ApplePanels = __importStar(require("./applePanels"));
76
76
  exports.AstericsGrid = __importStar(require("./astericsGrid"));
77
+ exports.GotalkNow = __importStar(require("./gotalkNow"));
77
78
  exports.Translation = __importStar(require("./translation"));
78
79
  const dotProcessor_1 = require("./processors/dotProcessor");
79
80
  const excelProcessor_1 = require("./processors/excelProcessor");
@@ -85,6 +86,7 @@ const touchchatProcessor_1 = require("./processors/touchchatProcessor");
85
86
  const applePanelsProcessor_1 = require("./processors/applePanelsProcessor");
86
87
  const astericsGridProcessor_1 = require("./processors/astericsGridProcessor");
87
88
  const obfsetProcessor_1 = require("./processors/obfsetProcessor");
89
+ const gotalkNowProcessor_1 = require("./processors/gotalkNowProcessor");
88
90
  /**
89
91
  * Factory function to get the appropriate processor for a file extension
90
92
  * @param filePathOrExtension - File path or extension (e.g., '.dot', '/path/to/file.obf')
@@ -124,6 +126,8 @@ function getProcessor(filePathOrExtension, options) {
124
126
  return new applePanelsProcessor_1.ApplePanelsProcessor(options);
125
127
  case '.grd':
126
128
  return new astericsGridProcessor_1.AstericsGridProcessor(options);
129
+ case '.gtbz':
130
+ return new gotalkNowProcessor_1.GotalkNowProcessor(options);
127
131
  default:
128
132
  throw new Error(`Unsupported file extension: ${extension}`);
129
133
  }
@@ -147,6 +151,7 @@ function getSupportedExtensions() {
147
151
  '.ce',
148
152
  '.plist',
149
153
  '.grd',
154
+ '.gtbz',
150
155
  ];
151
156
  }
152
157
  /**
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Helpers for decoding GoTalk NOW's NSKeyedArchiver-encoded values.
3
+ *
4
+ * GoTalk NOW stores UIColor and UIFont objects inside `<data>` tags as
5
+ * binary property lists (NSKeyedArchiver). Rather than pulling in a full
6
+ * bplist parser, we exploit the fact that the archived objects embed
7
+ * human-readable ASCII representations of the component values, e.g. an
8
+ * NSRGB colour appears as "0.908 0.355 0.522" and a font name appears as
9
+ * "Futura-Medium".
10
+ */
11
+ /**
12
+ * Decode an NSKeyedArchiver-encoded UIColor into a #rrggbb hex string.
13
+ *
14
+ * NSRGB / NSCalibratedRGB colours store a human-readable "R G B [A]" string
15
+ * (e.g. "0.908 0.355 0.522") inside the archive — this is the only encoding we
16
+ * can reliably read without a full binary-plist parser. NSWhite and
17
+ * UISystemColor values store their components as raw IEEE-754 floats, so we
18
+ * return undefined for those rather than risk an incorrect colour.
19
+ */
20
+ export declare function decodeNsColor(buffer: Uint8Array | Buffer | undefined): string | undefined;
21
+ /**
22
+ * Decode an NSKeyedArchiver-encoded UIFont into its family name.
23
+ * Font size is encoded as a raw IEEE-754 float and is not extracted.
24
+ */
25
+ export declare function decodeNsFont(buffer: Uint8Array | Buffer | undefined): {
26
+ fontFamily?: string;
27
+ };