@willwade/aac-processors 0.0.11 → 0.0.13

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 (56) hide show
  1. package/README.md +44 -41
  2. package/dist/cli/index.js +7 -0
  3. package/dist/core/analyze.js +1 -0
  4. package/dist/core/treeStructure.d.ts +45 -2
  5. package/dist/core/treeStructure.js +22 -3
  6. package/dist/index.d.ts +2 -1
  7. package/dist/index.js +20 -3
  8. package/dist/{analytics → optional/analytics}/history.d.ts +15 -4
  9. package/dist/{analytics → optional/analytics}/history.js +3 -3
  10. package/dist/optional/analytics/index.d.ts +30 -0
  11. package/dist/optional/analytics/index.js +78 -0
  12. package/dist/optional/analytics/metrics/comparison.d.ts +36 -0
  13. package/dist/optional/analytics/metrics/comparison.js +334 -0
  14. package/dist/optional/analytics/metrics/core.d.ts +45 -0
  15. package/dist/optional/analytics/metrics/core.js +575 -0
  16. package/dist/optional/analytics/metrics/effort.d.ts +147 -0
  17. package/dist/optional/analytics/metrics/effort.js +211 -0
  18. package/dist/optional/analytics/metrics/index.d.ts +15 -0
  19. package/dist/optional/analytics/metrics/index.js +36 -0
  20. package/dist/optional/analytics/metrics/obl-types.d.ts +93 -0
  21. package/dist/optional/analytics/metrics/obl-types.js +7 -0
  22. package/dist/optional/analytics/metrics/obl.d.ts +40 -0
  23. package/dist/optional/analytics/metrics/obl.js +287 -0
  24. package/dist/optional/analytics/metrics/sentence.d.ts +49 -0
  25. package/dist/optional/analytics/metrics/sentence.js +112 -0
  26. package/dist/optional/analytics/metrics/types.d.ts +157 -0
  27. package/dist/optional/analytics/metrics/types.js +7 -0
  28. package/dist/optional/analytics/metrics/vocabulary.d.ts +65 -0
  29. package/dist/optional/analytics/metrics/vocabulary.js +142 -0
  30. package/dist/optional/analytics/reference/index.d.ts +51 -0
  31. package/dist/optional/analytics/reference/index.js +102 -0
  32. package/dist/optional/analytics/utils/idGenerator.d.ts +59 -0
  33. package/dist/optional/analytics/utils/idGenerator.js +96 -0
  34. package/dist/optional/symbolTools.js +13 -16
  35. package/dist/processors/astericsGridProcessor.d.ts +15 -0
  36. package/dist/processors/astericsGridProcessor.js +17 -0
  37. package/dist/processors/gridset/helpers.d.ts +4 -1
  38. package/dist/processors/gridset/helpers.js +4 -0
  39. package/dist/processors/gridset/pluginTypes.js +51 -50
  40. package/dist/processors/gridset/symbolExtractor.js +3 -2
  41. package/dist/processors/gridset/symbolSearch.js +9 -7
  42. package/dist/processors/gridsetProcessor.js +82 -20
  43. package/dist/processors/index.d.ts +1 -0
  44. package/dist/processors/index.js +5 -3
  45. package/dist/processors/obfProcessor.js +37 -2
  46. package/dist/processors/obfsetProcessor.d.ts +26 -0
  47. package/dist/processors/obfsetProcessor.js +179 -0
  48. package/dist/processors/snap/helpers.d.ts +5 -1
  49. package/dist/processors/snap/helpers.js +5 -0
  50. package/dist/processors/snapProcessor.d.ts +2 -0
  51. package/dist/processors/snapProcessor.js +184 -5
  52. package/dist/processors/touchchatProcessor.js +50 -4
  53. package/dist/types/aac.d.ts +67 -0
  54. package/dist/types/aac.js +33 -0
  55. package/dist/validation/gridsetValidator.js +10 -0
  56. package/package.json +1 -1
@@ -106,10 +106,10 @@ function detectPluginCellType(content) {
106
106
  if (!content) {
107
107
  return { cellType: Grid3CellType.Regular };
108
108
  }
109
- const contentType = content.ContentType || content.contenttype || content.ContentType;
110
- const contentSubType = content.ContentSubType || content.contentsubtype || content.ContentSubType;
109
+ const contentType = content.ContentType || content.contenttype;
110
+ const contentSubType = content.ContentSubType || content.contentsubtype;
111
111
  // Workspace cells - full editing workspaces
112
- if (contentType === 'Workspace') {
112
+ if (contentType === 'Workspace' || content.Style?.BasedOnStyle === 'Workspace') {
113
113
  return {
114
114
  cellType: Grid3CellType.Workspace,
115
115
  subType: contentSubType || undefined,
@@ -118,7 +118,7 @@ function detectPluginCellType(content) {
118
118
  };
119
119
  }
120
120
  // LiveCell detection - dynamic content displays
121
- if (contentType === 'LiveCell') {
121
+ if (contentType === 'LiveCell' || content.Style?.BasedOnStyle === 'LiveCell') {
122
122
  return {
123
123
  cellType: Grid3CellType.LiveCell,
124
124
  liveCellType: contentSubType || undefined,
@@ -127,7 +127,7 @@ function detectPluginCellType(content) {
127
127
  };
128
128
  }
129
129
  // AutoContent detection - dynamic word/content suggestions
130
- if (contentType === 'AutoContent') {
130
+ if (contentType === 'AutoContent' || content.Style?.BasedOnStyle === 'AutoContent') {
131
131
  const autoContentType = extractAutoContentType(content);
132
132
  return {
133
133
  cellType: Grid3CellType.AutoContent,
@@ -172,38 +172,38 @@ function inferWorkspacePlugin(subType) {
172
172
  return undefined;
173
173
  const normalized = subType.toLowerCase();
174
174
  if (normalized.includes('chat'))
175
- return 'chat';
175
+ return 'Grid3.Chat';
176
176
  if (normalized.includes('email') || normalized.includes('mail'))
177
- return 'email';
178
- if (normalized.includes('word') || normalized.includes('processor'))
179
- return 'wordprocessor';
177
+ return 'Grid3.Email';
178
+ if (normalized.includes('word') || normalized.includes('doc'))
179
+ return 'Grid3.WordProcessor';
180
180
  if (normalized.includes('phone'))
181
- return 'phone';
181
+ return 'Grid3.Phone';
182
182
  if (normalized.includes('sms') || normalized.includes('text'))
183
- return 'sms';
184
- if (normalized.includes('web') || normalized.includes('browser'))
185
- return 'webbrowser';
186
- if (normalized.includes('computer') || normalized.includes('control'))
187
- return 'computercontrol';
188
- if (normalized.includes('calculator') || normalized.includes('calc'))
189
- return 'calculator';
190
- if (normalized.includes('timer') || normalized.includes('stopwatch'))
191
- return 'timer';
183
+ return 'Grid3.Sms';
184
+ if (normalized.includes('browser') || normalized.includes('web'))
185
+ return 'Grid3.WebBrowser';
186
+ if (normalized.includes('computer'))
187
+ return 'Grid3.ComputerControl';
188
+ if (normalized.includes('calc'))
189
+ return 'Grid3.Calculator';
190
+ if (normalized.includes('timer'))
191
+ return 'Grid3.Timer';
192
192
  if (normalized.includes('music') || normalized.includes('video'))
193
- return 'musicvideo';
193
+ return 'Grid3.MusicVideo';
194
194
  if (normalized.includes('photo') || normalized.includes('image'))
195
- return 'photos';
195
+ return 'Grid3.Photos';
196
196
  if (normalized.includes('contact'))
197
- return 'contacts';
197
+ return 'Grid3.Contacts';
198
198
  if (normalized.includes('learning'))
199
- return 'interactivelearning';
200
- if (normalized.includes('message') && normalized.includes('bank'))
201
- return 'messagebanking';
202
- if (normalized.includes('env') || normalized.includes('ir'))
203
- return 'environmentcontrol';
204
- if (normalized.includes('setting'))
205
- return 'settings';
206
- return undefined;
199
+ return 'Grid3.InteractiveLearning';
200
+ if (normalized.includes('message') && normalized.includes('banking'))
201
+ return 'Grid3.MessageBanking';
202
+ if (normalized.includes('control'))
203
+ return 'Grid3.EnvironmentControl';
204
+ if (normalized.includes('settings'))
205
+ return 'Grid3.Settings';
206
+ return `Grid3.${subType}`;
207
207
  }
208
208
  /**
209
209
  * Infer plugin ID from live cell type
@@ -212,24 +212,25 @@ function inferLiveCellPlugin(liveCellType) {
212
212
  if (!liveCellType)
213
213
  return undefined;
214
214
  const normalized = liveCellType.toLowerCase();
215
- if (normalized.includes('clock') || normalized.includes('time') || normalized.includes('date')) {
216
- return 'clock';
217
- }
215
+ if (normalized.includes('clock'))
216
+ return 'Grid3.Clock';
217
+ if (normalized.includes('date'))
218
+ return 'Grid3.Clock';
218
219
  if (normalized.includes('volume'))
219
- return 'speech';
220
+ return 'Grid3.Volume';
220
221
  if (normalized.includes('speed'))
221
- return 'speech';
222
+ return 'Grid3.Speed';
222
223
  if (normalized.includes('voice'))
223
- return 'speech';
224
+ return 'Grid3.Speech';
224
225
  if (normalized.includes('message'))
225
- return 'chat';
226
+ return 'Grid3.Chat';
226
227
  if (normalized.includes('battery'))
227
- return 'settings';
228
- if (normalized.includes('wifi') || normalized.includes('network'))
229
- return 'settings';
228
+ return 'Grid3.Battery';
229
+ if (normalized.includes('wifi'))
230
+ return 'Grid3.Wifi';
230
231
  if (normalized.includes('bluetooth'))
231
- return 'settings';
232
- return undefined;
232
+ return 'Grid3.Bluetooth';
233
+ return `Grid3.${liveCellType}`;
233
234
  }
234
235
  /**
235
236
  * Infer plugin ID from auto content type
@@ -239,24 +240,24 @@ function inferAutoContentPlugin(autoContentType) {
239
240
  return undefined;
240
241
  const normalized = autoContentType.toLowerCase();
241
242
  if (normalized.includes('voice') || normalized.includes('speed'))
242
- return 'speech';
243
+ return 'Grid3.Speech';
243
244
  if (normalized.includes('email') || normalized.includes('mail'))
244
- return 'email';
245
+ return 'Grid3.Email';
245
246
  if (normalized.includes('phone'))
246
- return 'phone';
247
+ return 'Grid3.Phone';
247
248
  if (normalized.includes('sms') || normalized.includes('text'))
248
- return 'sms';
249
+ return 'Grid3.Sms';
249
250
  if (normalized.includes('web') ||
250
251
  normalized.includes('favorite') ||
251
252
  normalized.includes('history')) {
252
- return 'webbrowser';
253
+ return 'Grid3.WebBrowser';
253
254
  }
254
255
  if (normalized.includes('prediction'))
255
- return 'prediction';
256
+ return 'Grid3.Prediction';
256
257
  if (normalized.includes('grammar'))
257
- return 'grammar';
258
+ return 'Grid3.Grammar';
258
259
  if (normalized.includes('context'))
259
- return 'autocontent';
260
+ return 'Grid3.AutoContent';
260
261
  return undefined;
261
262
  }
262
263
  /**
@@ -154,10 +154,11 @@ function extractSymbolLibraryImage(reference, options = {}) {
154
154
  };
155
155
  }
156
156
  // Successfully extracted!
157
- const format = detectImageFormat(resolved.data);
157
+ const data = resolved.data;
158
+ const format = data ? detectImageFormat(data) : 'unknown';
158
159
  return {
159
160
  found: true,
160
- data: resolved.data,
161
+ data,
161
162
  format,
162
163
  source: 'symbol-library',
163
164
  reference: reference,
@@ -126,13 +126,15 @@ function searchSymbols(searchTerm, options = {}) {
126
126
  // Exact match first
127
127
  if (index.searchTerms.has(lowerSearchTerm)) {
128
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
- });
129
+ if (symbolFilename) {
130
+ results.push({
131
+ searchTerm: lowerSearchTerm,
132
+ symbolFilename,
133
+ displayName: index.filenames.get(symbolFilename) || lowerSearchTerm,
134
+ library: libraryName,
135
+ exactMatch: true,
136
+ });
137
+ }
136
138
  }
137
139
  // Fuzzy match if enabled
138
140
  if (options.fuzzyMatch !== false) {
@@ -19,6 +19,7 @@ const pluginTypes_1 = require("./gridset/pluginTypes");
19
19
  const commands_1 = require("./gridset/commands");
20
20
  const symbols_1 = require("./gridset/symbols");
21
21
  const resolver_2 = require("./gridset/resolver");
22
+ const idGenerator_1 = require("../optional/analytics/utils/idGenerator");
22
23
  class GridsetProcessor extends baseProcessor_1.BaseProcessor {
23
24
  constructor(options) {
24
25
  super(options);
@@ -489,18 +490,62 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
489
490
  const cellY = Math.max(0, parseInt(String(cell['@_Y'] || '1'), 10) - 1);
490
491
  const colSpan = parseInt(String(cell['@_ColumnSpan'] || '1'), 10);
491
492
  const rowSpan = parseInt(String(cell['@_RowSpan'] || '1'), 10);
493
+ // Extract scan block number (1-8) for block scanning support
494
+ const scanBlock = parseInt(String(cell['@_ScanBlock'] || '1'), 10);
495
+ // Extract visibility from Grid 3's <Visibility> child element
496
+ // Grid 3 stores visibility as a child element, not an attribute
497
+ // Valid values: Visible, Hidden, Disabled, PointerAndTouchOnly, TouchOnly, PointerOnly
498
+ const grid3Visibility = cell.Visibility || cell.visibility;
499
+ // Map Grid 3 visibility values to AAC standard values
500
+ // Grid 3 can have additional values like TouchOnly, PointerOnly that map to PointerAndTouchOnly
501
+ let cellVisibility;
502
+ if (grid3Visibility) {
503
+ const vis = String(grid3Visibility);
504
+ // Direct mapping for standard values
505
+ if (vis === 'Visible' ||
506
+ vis === 'Hidden' ||
507
+ vis === 'Disabled' ||
508
+ vis === 'PointerAndTouchOnly') {
509
+ cellVisibility = vis;
510
+ }
511
+ // Map Grid 3 specific values to AAC standard
512
+ else if (vis === 'TouchOnly' || vis === 'PointerOnly') {
513
+ cellVisibility = 'PointerAndTouchOnly';
514
+ }
515
+ // Grid 3 may use 'Empty' for cells that exist but have no content
516
+ else if (vis === 'Empty') {
517
+ cellVisibility = 'Empty';
518
+ }
519
+ // Unknown visibility - default to Visible
520
+ else {
521
+ cellVisibility = undefined; // Let it default
522
+ }
523
+ }
492
524
  // Extract label from CaptionAndImage/Caption
493
525
  const content = cell.Content;
494
526
  const captionAndImage = content.CaptionAndImage || content.captionAndImage;
495
527
  let label = captionAndImage?.Caption || captionAndImage?.caption || '';
528
+ // Check if cell has an image/symbol (needed to decide if we should keep it)
529
+ const hasImageCandidate = !!(captionAndImage?.Image ||
530
+ captionAndImage?.image ||
531
+ captionAndImage?.ImageName ||
532
+ captionAndImage?.imageName ||
533
+ captionAndImage?.Symbol ||
534
+ captionAndImage?.symbol);
496
535
  // If no caption, try other sources or create a placeholder
497
536
  if (!label) {
498
- // For cells without captions (like AutoContent cells), create a meaningful label
537
+ // For cells without captions, check if they have images/symbols before skipping
499
538
  if (content.ContentType === 'AutoContent') {
500
539
  label = `AutoContent_${idx}`;
501
540
  }
541
+ else if (hasImageCandidate ||
542
+ content.ContentType === 'Workspace' ||
543
+ content.ContentType === 'LiveCell') {
544
+ // Keep cells with images/symbols even if no caption
545
+ label = `Cell_${idx}`;
546
+ }
502
547
  else {
503
- return; // Skip cells without labels
548
+ return; // Skip cells without labels AND without images/symbols
504
549
  }
505
550
  }
506
551
  const message = label; // Use caption as message
@@ -922,12 +967,14 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
922
967
  message: String(message),
923
968
  targetPageId: navigationTarget ? String(navigationTarget) : undefined,
924
969
  semanticAction: semanticAction,
970
+ semantic_id: cell.semantic_id || cell.SemanticId || undefined, // Extract semantic_id if present
925
971
  image: declaredImageName,
926
972
  resolvedImageEntry: resolvedImageEntry,
927
973
  x: cellX,
928
974
  y: cellY,
929
975
  columnSpan: colSpan,
930
976
  rowSpan: rowSpan,
977
+ scanBlock: scanBlock, // Add scan block number for block scanning metrics
931
978
  contentType: pluginMetadata.cellType === pluginTypes_1.Grid3CellType.Regular
932
979
  ? 'Normal'
933
980
  : pluginMetadata.cellType === pluginTypes_1.Grid3CellType.Workspace
@@ -940,6 +987,7 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
940
987
  pluginMetadata.autoContentType,
941
988
  symbolLibrary: symbolLibraryRef?.library || undefined,
942
989
  symbolPath: symbolLibraryRef?.path || undefined,
990
+ visibility: cellVisibility,
943
991
  style: {
944
992
  ...cellStyle,
945
993
  ...inlineStyle, // Inline styles override referenced styles
@@ -963,6 +1011,29 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
963
1011
  });
964
1012
  // Set the page's grid layout
965
1013
  page.grid = gridLayout;
1014
+ // Generate clone_id for each button in the grid
1015
+ const semanticIds = [];
1016
+ const cloneIds = [];
1017
+ gridLayout.forEach((row, rowIndex) => {
1018
+ row.forEach((btn, colIndex) => {
1019
+ if (btn) {
1020
+ // Generate clone_id based on position and label
1021
+ btn.clone_id = (0, idGenerator_1.generateCloneId)(maxRows, maxCols, rowIndex, colIndex, btn.label);
1022
+ cloneIds.push(btn.clone_id);
1023
+ // Track semantic_id if present
1024
+ if (btn.semantic_id) {
1025
+ semanticIds.push(btn.semantic_id);
1026
+ }
1027
+ }
1028
+ });
1029
+ });
1030
+ // Track IDs on the page
1031
+ if (semanticIds.length > 0) {
1032
+ page.semantic_ids = semanticIds;
1033
+ }
1034
+ if (cloneIds.length > 0) {
1035
+ page.clone_ids = cloneIds;
1036
+ }
966
1037
  }
967
1038
  tree.addPage(page);
968
1039
  }
@@ -1143,30 +1214,18 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
1143
1214
  GridGuid: page.id,
1144
1215
  // Calculate grid dimensions based on actual layout
1145
1216
  ColumnDefinitions: this.calculateColumnDefinitions(page),
1146
- RowDefinitions: this.calculateRowDefinitions(page),
1217
+ RowDefinitions: this.calculateRowDefinitions(page, false), // No automatic workspace row injection
1147
1218
  AutoContentCommands: '',
1148
1219
  Cells: page.buttons.length > 0
1149
1220
  ? {
1150
1221
  Cell: [
1151
- // Add workspace/message bar cell at the top of ALL pages
1152
- // Grid3 uses 0-based coordinates; omit X and Y to use defaults (0, 0)
1153
- {
1154
- '@_ColumnSpan': 4,
1155
- Content: {
1156
- ContentType: 'Workspace',
1157
- ContentSubType: 'Chat',
1158
- Style: {
1159
- BasedOnStyle: 'Workspace',
1160
- },
1161
- },
1162
- },
1163
1222
  // Regular button cells
1164
1223
  ...this.filterPageButtons(page.buttons).map((button, btnIndex) => {
1165
1224
  const buttonStyleId = button.style ? addStyle(button.style) : '';
1166
1225
  // Find button position in grid layout
1167
1226
  const position = this.findButtonPosition(page, button, btnIndex);
1168
- // Shift all buttons down by 1 row to make room for workspace
1169
- const yOffset = 1;
1227
+ // Use position directly from tree
1228
+ const yOffset = 0;
1170
1229
  // Build CaptionAndImage object
1171
1230
  const captionAndImage = {
1172
1231
  Caption: button.label || '',
@@ -1207,6 +1266,8 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
1207
1266
  '@_ColumnSpan': position.columnSpan,
1208
1267
  '@_RowSpan': position.rowSpan,
1209
1268
  Content: {
1269
+ ContentType: button.contentType === 'Normal' ? undefined : button.contentType,
1270
+ ContentSubType: button.contentSubType,
1210
1271
  Commands: this.generateCommandsFromSemanticAction(button, tree),
1211
1272
  CaptionAndImage: captionAndImage,
1212
1273
  },
@@ -1322,15 +1383,16 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
1322
1383
  };
1323
1384
  }
1324
1385
  // Helper method to calculate row definitions based on page layout
1325
- calculateRowDefinitions(page) {
1386
+ calculateRowDefinitions(page, addWorkspaceOffset = false) {
1326
1387
  let maxRows = 4; // Default minimum
1388
+ const offset = addWorkspaceOffset ? 1 : 0;
1327
1389
  if (page.grid && page.grid.length > 0) {
1328
- maxRows = Math.max(maxRows, page.grid.length);
1390
+ maxRows = Math.max(maxRows, page.grid.length + offset);
1329
1391
  }
1330
1392
  else {
1331
1393
  // Fallback: estimate from button count
1332
1394
  const estimatedCols = Math.ceil(Math.sqrt(page.buttons.length));
1333
- maxRows = Math.max(4, Math.ceil(page.buttons.length / estimatedCols));
1395
+ maxRows = Math.max(4, Math.ceil(page.buttons.length / estimatedCols)) + offset;
1334
1396
  }
1335
1397
  return {
1336
1398
  RowDefinition: Array(maxRows).fill({}),
@@ -7,6 +7,7 @@ export { OpmlProcessor } from './opmlProcessor';
7
7
  export { SnapProcessor } from './snapProcessor';
8
8
  export { TouchChatProcessor } from './touchchatProcessor';
9
9
  export { AstericsGridProcessor } from './astericsGridProcessor';
10
+ export { ObfsetProcessor } from './obfsetProcessor';
10
11
  export { getPageTokenImageMap, getAllowedImageEntries, openImage, generateGrid3Guid, createSettingsXml, createFileMapXml, getCommonDocumentsPath, findGrid3UserPaths, findGrid3HistoryDatabases, findGrid3Users, findGrid3Vocabularies, findGrid3UserHistory, isGrid3Installed, readGrid3History, readGrid3HistoryForUser, readAllGrid3History, type Grid3UserPath, type Grid3VocabularyPath, type Grid3HistoryEntry, } from './gridset/helpers';
11
12
  export { getPageTokenImageMap as getGridsetPageTokenImageMap, getAllowedImageEntries as getGridsetAllowedImageEntries, openImage as openGridsetImage, generateGrid3Guid as generateGridsetGuid, createSettingsXml as createGridsetSettingsXml, createFileMapXml as createGridsetFileMapXml, getCommonDocumentsPath as getGridsetCommonDocumentsPath, findGrid3UserPaths as findGridsetUserPaths, findGrid3HistoryDatabases as findGridsetHistoryDatabases, findGrid3Users as findGridsetUsers, findGrid3Vocabularies as findGridsetVocabularies, findGrid3UserHistory as findGridsetUserHistory, isGrid3Installed as isGridsetInstalled, readGrid3History as readGridsetHistory, readGrid3HistoryForUser as readGridsetHistoryForUser, readAllGrid3History as readAllGridsetHistory, } from './gridset/helpers';
12
13
  export { resolveGrid3CellImage } from './gridset/resolver';
@@ -14,9 +14,9 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.rgbaToHex = exports.getNamedColor = exports.resolveGridsetPasswordFromEnv = exports.resolveGridsetPassword = exports.wordlistToXml = exports.updateWordlist = exports.extractWordlists = exports.createWordlist = exports.resolveGrid3CellImage = exports.readAllGridsetHistory = exports.readGridsetHistoryForUser = exports.readGridsetHistory = exports.isGridsetInstalled = exports.findGridsetUserHistory = exports.findGridsetVocabularies = exports.findGridsetUsers = exports.findGridsetHistoryDatabases = exports.findGridsetUserPaths = exports.getGridsetCommonDocumentsPath = exports.createGridsetFileMapXml = exports.createGridsetSettingsXml = exports.generateGridsetGuid = exports.openGridsetImage = exports.getGridsetAllowedImageEntries = exports.getGridsetPageTokenImageMap = exports.readAllGrid3History = exports.readGrid3HistoryForUser = exports.readGrid3History = exports.isGrid3Installed = exports.findGrid3UserHistory = exports.findGrid3Vocabularies = exports.findGrid3Users = exports.findGrid3HistoryDatabases = exports.findGrid3UserPaths = exports.getCommonDocumentsPath = exports.createFileMapXml = exports.createSettingsXml = exports.generateGrid3Guid = exports.openImage = exports.getAllowedImageEntries = exports.getPageTokenImageMap = exports.AstericsGridProcessor = exports.TouchChatProcessor = exports.SnapProcessor = exports.OpmlProcessor = exports.ObfProcessor = exports.GridsetProcessor = exports.ExcelProcessor = exports.DotProcessor = exports.ApplePanelsProcessor = void 0;
18
- exports.SYMBOL_LIBRARIES = exports.symbolReferenceToFilename = exports.getSymbolSearchIndexesDir = exports.getSymbolLibrariesDir = exports.getDefaultGrid3Path = exports.getSymbolLibraryDisplayName = exports.isKnownSymbolLibrary = exports.getSymbolPath = exports.getSymbolLibraryName = exports.createSymbolReference = exports.analyzeSymbolUsage = exports.extractSymbolReferences = exports.getSymbolLibraryInfo = exports.getAvailableSymbolLibraries = exports.resolveSymbolReference = exports.isSymbolReference = exports.parseSymbolReference = exports.Grid3CommandCategory = exports.GRID3_COMMANDS = exports.extractCommandParameters = exports.getAllPluginIds = exports.getAllCommandIds = exports.getCommandsByCategory = exports.getCommandsByPlugin = exports.getCommandDefinition = exports.detectCommand = exports.isRegularCell = exports.isAutoContentCell = exports.isLiveCell = exports.isWorkspaceCell = exports.getCellTypeDisplayName = exports.AUTOCONTENT_TYPES = exports.LIVECELL_TYPES = exports.WORKSPACE_TYPES = exports.Grid3CellType = exports.detectPluginCellType = exports.ensureAlphaChannelFromStyles = exports.SHAPE_NAMES = exports.CellBackgroundShape = exports.createCategoryStyle = exports.createDefaultStylesXml = exports.CATEGORY_STYLES = exports.DEFAULT_GRID3_STYLES = exports.ensureAlphaChannel = exports.normalizeColor = exports.darkenColor = exports.toHexColor = exports.clampAlpha = exports.clampColorChannel = exports.channelToHex = void 0;
19
- exports.openTouchChatImage = exports.getTouchChatAllowedImageEntries = exports.getTouchChatPageTokenImageMap = exports.readSnapUsageForUser = exports.readSnapUsage = exports.isSnapInstalled = exports.findSnapUserHistory = exports.findSnapUserVocabularies = exports.findSnapUsers = exports.findSnapPackagePath = exports.findSnapPackages = exports.openSnapImage = exports.getSnapAllowedImageEntries = exports.getSnapPageTokenImageMap = exports.getSymbolSearchStats = exports.countLibrarySymbols = exports.getSearchSuggestions = exports.getAllSearchTerms = exports.getSymbolDisplayName = exports.getSymbolFilename = exports.searchSymbolsWithReferences = exports.searchSymbols = exports.loadSearchIndexes = exports.parsePixFile = exports.createSymbolManifest = exports.exportSymbolReferencesToCsv = exports.suggestExtractionStrategy = exports.analyzeSymbolExtraction = exports.convertToAstericsImage = exports.extractSymbolLibraryImage = exports.extractButtonImage = exports.getSymbolSearchDir = exports.getSymbolsDir = exports.parseImageSymbolReference = exports.isSymbolLibraryReference = void 0;
17
+ exports.getNamedColor = exports.resolveGridsetPasswordFromEnv = exports.resolveGridsetPassword = exports.wordlistToXml = exports.updateWordlist = exports.extractWordlists = exports.createWordlist = exports.resolveGrid3CellImage = exports.readAllGridsetHistory = exports.readGridsetHistoryForUser = exports.readGridsetHistory = exports.isGridsetInstalled = exports.findGridsetUserHistory = exports.findGridsetVocabularies = exports.findGridsetUsers = exports.findGridsetHistoryDatabases = exports.findGridsetUserPaths = exports.getGridsetCommonDocumentsPath = exports.createGridsetFileMapXml = exports.createGridsetSettingsXml = exports.generateGridsetGuid = exports.openGridsetImage = exports.getGridsetAllowedImageEntries = exports.getGridsetPageTokenImageMap = exports.readAllGrid3History = exports.readGrid3HistoryForUser = exports.readGrid3History = exports.isGrid3Installed = exports.findGrid3UserHistory = exports.findGrid3Vocabularies = exports.findGrid3Users = exports.findGrid3HistoryDatabases = exports.findGrid3UserPaths = exports.getCommonDocumentsPath = exports.createFileMapXml = exports.createSettingsXml = exports.generateGrid3Guid = exports.openImage = exports.getAllowedImageEntries = exports.getPageTokenImageMap = exports.ObfsetProcessor = exports.AstericsGridProcessor = exports.TouchChatProcessor = exports.SnapProcessor = exports.OpmlProcessor = exports.ObfProcessor = exports.GridsetProcessor = exports.ExcelProcessor = exports.DotProcessor = exports.ApplePanelsProcessor = void 0;
18
+ exports.symbolReferenceToFilename = exports.getSymbolSearchIndexesDir = exports.getSymbolLibrariesDir = exports.getDefaultGrid3Path = exports.getSymbolLibraryDisplayName = exports.isKnownSymbolLibrary = exports.getSymbolPath = exports.getSymbolLibraryName = exports.createSymbolReference = exports.analyzeSymbolUsage = exports.extractSymbolReferences = exports.getSymbolLibraryInfo = exports.getAvailableSymbolLibraries = exports.resolveSymbolReference = exports.isSymbolReference = exports.parseSymbolReference = exports.Grid3CommandCategory = exports.GRID3_COMMANDS = exports.extractCommandParameters = exports.getAllPluginIds = exports.getAllCommandIds = exports.getCommandsByCategory = exports.getCommandsByPlugin = exports.getCommandDefinition = exports.detectCommand = exports.isRegularCell = exports.isAutoContentCell = exports.isLiveCell = exports.isWorkspaceCell = exports.getCellTypeDisplayName = exports.AUTOCONTENT_TYPES = exports.LIVECELL_TYPES = exports.WORKSPACE_TYPES = exports.Grid3CellType = exports.detectPluginCellType = exports.ensureAlphaChannelFromStyles = exports.SHAPE_NAMES = exports.CellBackgroundShape = exports.createCategoryStyle = exports.createDefaultStylesXml = exports.CATEGORY_STYLES = exports.DEFAULT_GRID3_STYLES = exports.ensureAlphaChannel = exports.normalizeColor = exports.darkenColor = exports.toHexColor = exports.clampAlpha = exports.clampColorChannel = exports.channelToHex = exports.rgbaToHex = void 0;
19
+ exports.openTouchChatImage = exports.getTouchChatAllowedImageEntries = exports.getTouchChatPageTokenImageMap = exports.readSnapUsageForUser = exports.readSnapUsage = exports.isSnapInstalled = exports.findSnapUserHistory = exports.findSnapUserVocabularies = exports.findSnapUsers = exports.findSnapPackagePath = exports.findSnapPackages = exports.openSnapImage = exports.getSnapAllowedImageEntries = exports.getSnapPageTokenImageMap = exports.getSymbolSearchStats = exports.countLibrarySymbols = exports.getSearchSuggestions = exports.getAllSearchTerms = exports.getSymbolDisplayName = exports.getSymbolFilename = exports.searchSymbolsWithReferences = exports.searchSymbols = exports.loadSearchIndexes = exports.parsePixFile = exports.createSymbolManifest = exports.exportSymbolReferencesToCsv = exports.suggestExtractionStrategy = exports.analyzeSymbolExtraction = exports.convertToAstericsImage = exports.extractSymbolLibraryImage = exports.extractButtonImage = exports.getSymbolSearchDir = exports.getSymbolsDir = exports.parseImageSymbolReference = exports.isSymbolLibraryReference = exports.SYMBOL_LIBRARIES = void 0;
20
20
  var applePanelsProcessor_1 = require("./applePanelsProcessor");
21
21
  Object.defineProperty(exports, "ApplePanelsProcessor", { enumerable: true, get: function () { return applePanelsProcessor_1.ApplePanelsProcessor; } });
22
22
  var dotProcessor_1 = require("./dotProcessor");
@@ -35,6 +35,8 @@ var touchchatProcessor_1 = require("./touchchatProcessor");
35
35
  Object.defineProperty(exports, "TouchChatProcessor", { enumerable: true, get: function () { return touchchatProcessor_1.TouchChatProcessor; } });
36
36
  var astericsGridProcessor_1 = require("./astericsGridProcessor");
37
37
  Object.defineProperty(exports, "AstericsGridProcessor", { enumerable: true, get: function () { return astericsGridProcessor_1.AstericsGridProcessor; } });
38
+ var obfsetProcessor_1 = require("./obfsetProcessor");
39
+ Object.defineProperty(exports, "ObfsetProcessor", { enumerable: true, get: function () { return obfsetProcessor_1.ObfsetProcessor; } });
38
40
  // Gridset (Grid 3) helpers
39
41
  var helpers_1 = require("./gridset/helpers");
40
42
  Object.defineProperty(exports, "getPageTokenImageMap", { enumerable: true, get: function () { return helpers_1.getPageTokenImageMap; } });
@@ -6,12 +6,22 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.ObfProcessor = void 0;
7
7
  const baseProcessor_1 = require("../core/baseProcessor");
8
8
  const treeStructure_1 = require("../core/treeStructure");
9
- // Removed unused import: FileProcessor
9
+ const idGenerator_1 = require("../optional/analytics/utils/idGenerator");
10
10
  const adm_zip_1 = __importDefault(require("adm-zip"));
11
11
  const fs_1 = __importDefault(require("fs"));
12
- // Removed unused import: path
13
12
  const obfValidator_1 = require("../validation/obfValidator");
14
13
  const OBF_FORMAT_VERSION = 'open-board-0.1';
14
+ /**
15
+ * Map OBF hidden value to AAC standard visibility
16
+ * OBF: true = hidden, false/undefined = visible
17
+ * Maps to: 'Hidden' | 'Visible' | undefined
18
+ */
19
+ function mapObfVisibility(hidden) {
20
+ if (hidden === undefined) {
21
+ return undefined; // Default to visible
22
+ }
23
+ return hidden ? 'Hidden' : 'Visible';
24
+ }
15
25
  class ObfProcessor extends baseProcessor_1.BaseProcessor {
16
26
  constructor(options) {
17
27
  super(options);
@@ -42,12 +52,14 @@ class ObfProcessor extends baseProcessor_1.BaseProcessor {
42
52
  id: String(btn?.id || ''),
43
53
  label: String(btn?.label || ''),
44
54
  message: String(btn?.vocalization || btn?.label || ''),
55
+ visibility: mapObfVisibility(btn.hidden),
45
56
  style: {
46
57
  backgroundColor: btn.background_color,
47
58
  borderColor: btn.border_color,
48
59
  },
49
60
  semanticAction,
50
61
  targetPageId: btn.load_board?.path,
62
+ semantic_id: btn.semantic_id, // Extract semantic_id if present
51
63
  });
52
64
  });
53
65
  const buttonMap = new Map(buttons.map((btn) => [btn.id, btn]));
@@ -105,6 +117,29 @@ class ObfProcessor extends baseProcessor_1.BaseProcessor {
105
117
  }
106
118
  }
107
119
  page.grid = grid;
120
+ // Generate clone_id for buttons in the grid
121
+ const semanticIds = [];
122
+ const cloneIds = [];
123
+ grid.forEach((row, rowIndex) => {
124
+ row.forEach((btn, colIndex) => {
125
+ if (btn) {
126
+ // Generate clone_id based on position and label
127
+ btn.clone_id = (0, idGenerator_1.generateCloneId)(rows, cols, rowIndex, colIndex, btn.label);
128
+ cloneIds.push(btn.clone_id);
129
+ // Track semantic_id if present
130
+ if (btn.semantic_id) {
131
+ semanticIds.push(btn.semantic_id);
132
+ }
133
+ }
134
+ });
135
+ });
136
+ // Track IDs on the page
137
+ if (semanticIds.length > 0) {
138
+ page.semantic_ids = semanticIds;
139
+ }
140
+ if (cloneIds.length > 0) {
141
+ page.clone_ids = cloneIds;
142
+ }
108
143
  }
109
144
  }
110
145
  return page;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * OBF Set Processor - Handles JSON-formatted .obfset files
3
+ * These are pre-extracted board sets in JSON array format
4
+ */
5
+ import { AACTree } from '../core/treeStructure';
6
+ import { BaseProcessor, ProcessorOptions } from '../core/baseProcessor';
7
+ export declare class ObfsetProcessor extends BaseProcessor {
8
+ constructor(options?: ProcessorOptions);
9
+ /**
10
+ * Extract all text content
11
+ */
12
+ extractTexts(filePathOrBuffer: string | Buffer): string[];
13
+ /**
14
+ * Load an .obfset file (JSON array of boards)
15
+ */
16
+ loadIntoTree(filePathOrBuffer: string | Buffer): AACTree;
17
+ /**
18
+ * Process texts (not supported for .obfset currently)
19
+ */
20
+ processTexts(_filePathOrBuffer: string | Buffer, _translations: Map<string, string>, _outputPath: string): Buffer;
21
+ /**
22
+ * Save tree structure back to file
23
+ */
24
+ saveFromTree(_tree: AACTree, _outputPath: string): void;
25
+ supportsExtension(extension: string): boolean;
26
+ }