@willwade/aac-processors 0.2.3 → 0.2.5

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 (47) hide show
  1. package/dist/browser/core/treeStructure.js +3 -1
  2. package/dist/browser/metrics.js +2 -0
  3. package/dist/browser/processors/astericsGridProcessor.js +21 -12
  4. package/dist/browser/processors/gridset/helpers.js +3 -3
  5. package/dist/browser/processors/gridsetProcessor.js +269 -239
  6. package/dist/browser/processors/obfProcessor.js +4 -4
  7. package/dist/browser/processors/snap/helpers.js +3 -3
  8. package/dist/browser/processors/snapProcessor.js +2 -2
  9. package/dist/browser/processors/touchchatProcessor.js +6 -6
  10. package/dist/browser/utilities/analytics/metrics/core.js +213 -8
  11. package/dist/browser/utilities/analytics/metrics/vocabulary.js +13 -1
  12. package/dist/browser/utilities/analytics/morphology/engine.js +910 -0
  13. package/dist/browser/utilities/analytics/morphology/grid3VerbsParser.js +455 -0
  14. package/dist/browser/utilities/analytics/morphology/index.js +3 -0
  15. package/dist/browser/utilities/analytics/morphology/types.js +1 -0
  16. package/dist/browser/utilities/analytics/morphology/wordFormGenerator.js +74 -0
  17. package/dist/core/treeStructure.d.ts +17 -1
  18. package/dist/core/treeStructure.js +3 -1
  19. package/dist/index.node.d.ts +2 -0
  20. package/dist/index.node.js +6 -1
  21. package/dist/metrics.d.ts +3 -0
  22. package/dist/metrics.js +5 -1
  23. package/dist/processors/astericsGridProcessor.js +21 -12
  24. package/dist/processors/excelProcessor.js +5 -1
  25. package/dist/processors/gridset/helpers.js +3 -3
  26. package/dist/processors/gridset/imageDebug.js +2 -2
  27. package/dist/processors/gridsetProcessor.js +269 -239
  28. package/dist/processors/obfProcessor.js +4 -4
  29. package/dist/processors/snap/helpers.js +3 -3
  30. package/dist/processors/snapProcessor.js +2 -2
  31. package/dist/processors/touchchatProcessor.js +6 -6
  32. package/dist/utilities/analytics/metrics/core.d.ts +14 -0
  33. package/dist/utilities/analytics/metrics/core.js +213 -8
  34. package/dist/utilities/analytics/metrics/types.d.ts +18 -3
  35. package/dist/utilities/analytics/metrics/vocabulary.d.ts +3 -0
  36. package/dist/utilities/analytics/metrics/vocabulary.js +13 -1
  37. package/dist/utilities/analytics/morphology/engine.d.ts +30 -0
  38. package/dist/utilities/analytics/morphology/engine.js +914 -0
  39. package/dist/utilities/analytics/morphology/grid3VerbsParser.d.ts +36 -0
  40. package/dist/utilities/analytics/morphology/grid3VerbsParser.js +485 -0
  41. package/dist/utilities/analytics/morphology/index.d.ts +5 -0
  42. package/dist/utilities/analytics/morphology/index.js +9 -0
  43. package/dist/utilities/analytics/morphology/types.d.ts +40 -0
  44. package/dist/utilities/analytics/morphology/types.js +2 -0
  45. package/dist/utilities/analytics/morphology/wordFormGenerator.d.ts +10 -0
  46. package/dist/utilities/analytics/morphology/wordFormGenerator.js +78 -0
  47. package/package.json +12 -11
@@ -465,7 +465,7 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
465
465
  }
466
466
  }
467
467
  }
468
- catch (e) {
468
+ catch (_e) {
469
469
  /* ignore: optional FileMap.xml may be missing or malformed */
470
470
  }
471
471
  // First, load styles from Settings0/Styles/styles.xml (Grid3 format)
@@ -536,7 +536,7 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
536
536
  const normalizedEntry = imageEntry.entryName.replace(/\\/g, '/');
537
537
  imageDataCache.set(normalizedEntry, data);
538
538
  }
539
- catch (err) {
539
+ catch (_err) {
540
540
  // Silently fail - individual image loading failures shouldn't break the entire load
541
541
  }
542
542
  }
@@ -569,7 +569,7 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
569
569
  }
570
570
  }
571
571
  }
572
- catch (e) {
572
+ catch (_e) {
573
573
  // Skip errors in first pass
574
574
  }
575
575
  }
@@ -584,7 +584,7 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
584
584
  xmlContent = (0, io_1.decodeText)(buffer);
585
585
  console.log(`[Gridset] Raw XML content (first 200 chars) for ${entry.entryName}:`, xmlContent.substring(0, 200));
586
586
  }
587
- catch (e) {
587
+ catch (_e) {
588
588
  // Skip unreadable files
589
589
  continue;
590
590
  }
@@ -939,10 +939,11 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
939
939
  }
940
940
  // Parse all command types from Grid3 and create semantic actions
941
941
  let semanticAction;
942
- let legacyAction = null;
942
+ let _legacyAction = null;
943
943
  // infer action type implicitly from commands; no explicit enum needed
944
944
  let navigationTarget;
945
945
  let detectedCommands = []; // Store detected command metadata
946
+ let buttonPos; // Part-of-speech from Action.InsertText
946
947
  const commands = content.Commands?.Command || content.commands?.command;
947
948
  let predictionWords;
948
949
  // Resolve image for this cell using FileMap and coordinate heuristics
@@ -1064,114 +1065,125 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
1064
1065
  if (gridTarget) {
1065
1066
  // Resolve grid name to grid ID for navigation
1066
1067
  const targetGridId = gridNameToIdMap.get(gridTarget) || gridTarget;
1068
+ // Always set navigationTarget even if another command already
1069
+ // set semanticAction (e.g. Jump.SetBookmark + Jump.To).
1067
1070
  navigationTarget = targetGridId;
1068
- // navigate action
1071
+ // Only set semanticAction if not already set by a prior command
1072
+ if (!semanticAction) {
1073
+ semanticAction = {
1074
+ category: treeStructure_1.AACSemanticCategory.NAVIGATION,
1075
+ intent: treeStructure_1.AACSemanticIntent.NAVIGATE_TO,
1076
+ targetId: targetGridId,
1077
+ platformData: {
1078
+ grid3: {
1079
+ commandId,
1080
+ parameters: { grid: gridTarget },
1081
+ },
1082
+ },
1083
+ fallback: {
1084
+ type: 'NAVIGATE',
1085
+ targetPageId: targetGridId,
1086
+ },
1087
+ };
1088
+ _legacyAction = {
1089
+ type: 'NAVIGATE',
1090
+ targetPageId: targetGridId,
1091
+ };
1092
+ }
1093
+ }
1094
+ break;
1095
+ }
1096
+ case 'Jump.Back':
1097
+ if (!semanticAction) {
1069
1098
  semanticAction = {
1070
1099
  category: treeStructure_1.AACSemanticCategory.NAVIGATION,
1071
- intent: treeStructure_1.AACSemanticIntent.NAVIGATE_TO,
1072
- targetId: targetGridId,
1100
+ intent: treeStructure_1.AACSemanticIntent.GO_BACK,
1073
1101
  platformData: {
1074
1102
  grid3: {
1075
1103
  commandId,
1076
- parameters: { grid: gridTarget },
1104
+ parameters: {},
1077
1105
  },
1078
1106
  },
1079
1107
  fallback: {
1080
- type: 'NAVIGATE',
1081
- targetPageId: targetGridId,
1108
+ type: 'ACTION',
1109
+ message: 'Go back',
1082
1110
  },
1083
1111
  };
1084
- legacyAction = {
1085
- type: 'NAVIGATE',
1086
- targetPageId: targetGridId,
1112
+ _legacyAction = {
1113
+ type: 'GO_BACK',
1087
1114
  };
1088
1115
  }
1089
1116
  break;
1090
- }
1091
- case 'Jump.Back':
1092
- // action
1093
- semanticAction = {
1094
- category: treeStructure_1.AACSemanticCategory.NAVIGATION,
1095
- intent: treeStructure_1.AACSemanticIntent.GO_BACK,
1096
- platformData: {
1097
- grid3: {
1098
- commandId,
1099
- parameters: {},
1100
- },
1101
- },
1102
- fallback: {
1103
- type: 'ACTION',
1104
- message: 'Go back',
1105
- },
1106
- };
1107
- legacyAction = {
1108
- type: 'GO_BACK',
1109
- };
1110
- break;
1111
1117
  case 'Jump.Home':
1112
1118
  case 'Jump.SetHome':
1113
- // action
1114
- navigationTarget = tree.rootId || undefined;
1115
- semanticAction = {
1116
- category: treeStructure_1.AACSemanticCategory.NAVIGATION,
1117
- intent: treeStructure_1.AACSemanticIntent.GO_HOME,
1118
- targetId: tree.rootId || undefined,
1119
- platformData: {
1120
- grid3: {
1121
- commandId,
1122
- parameters: {},
1119
+ if (!navigationTarget)
1120
+ navigationTarget = tree.rootId || undefined;
1121
+ if (!semanticAction) {
1122
+ semanticAction = {
1123
+ category: treeStructure_1.AACSemanticCategory.NAVIGATION,
1124
+ intent: treeStructure_1.AACSemanticIntent.GO_HOME,
1125
+ targetId: tree.rootId || undefined,
1126
+ platformData: {
1127
+ grid3: {
1128
+ commandId,
1129
+ parameters: {},
1130
+ },
1123
1131
  },
1124
- },
1125
- fallback: {
1126
- type: 'ACTION',
1127
- message: 'Go home',
1128
- },
1129
- };
1130
- legacyAction = {
1131
- type: 'GO_HOME',
1132
- };
1132
+ fallback: {
1133
+ type: 'ACTION',
1134
+ message: 'Go home',
1135
+ },
1136
+ };
1137
+ _legacyAction = {
1138
+ type: 'GO_HOME',
1139
+ };
1140
+ }
1133
1141
  break;
1134
1142
  case 'Jump.ToKeyboard': {
1135
1143
  // Navigate to the set keyboard if we found one in settings
1136
1144
  const keyboardGridName = tree.keyboardGridName;
1137
1145
  const keyboardPageId = gridNameToIdMap.get(keyboardGridName);
1138
- if (keyboardPageId) {
1146
+ if (keyboardPageId && !navigationTarget) {
1139
1147
  navigationTarget = keyboardPageId;
1140
1148
  }
1141
- semanticAction = {
1142
- category: treeStructure_1.AACSemanticCategory.NAVIGATION,
1143
- intent: treeStructure_1.AACSemanticIntent.GO_HOME, // Close enough to 'navigation to keyboard'
1144
- targetId: keyboardPageId,
1145
- platformData: {
1146
- grid3: {
1147
- commandId,
1148
- parameters: {},
1149
+ if (!semanticAction) {
1150
+ semanticAction = {
1151
+ category: treeStructure_1.AACSemanticCategory.NAVIGATION,
1152
+ intent: treeStructure_1.AACSemanticIntent.GO_HOME, // Close enough to 'navigation to keyboard'
1153
+ targetId: keyboardPageId,
1154
+ platformData: {
1155
+ grid3: {
1156
+ commandId,
1157
+ parameters: {},
1158
+ },
1149
1159
  },
1150
- },
1151
- fallback: {
1152
- type: 'NAVIGATE',
1153
- targetPageId: keyboardPageId,
1154
- },
1155
- };
1160
+ fallback: {
1161
+ type: 'NAVIGATE',
1162
+ targetPageId: keyboardPageId,
1163
+ },
1164
+ };
1165
+ }
1156
1166
  break;
1157
1167
  }
1158
1168
  case 'Action.InsertTextAndSpeak': {
1159
- const insertText = getParam('text');
1160
- semanticAction = {
1161
- category: treeStructure_1.AACSemanticCategory.COMMUNICATION,
1162
- intent: treeStructure_1.AACSemanticIntent.SPEAK_IMMEDIATE,
1163
- text: insertText,
1164
- platformData: {
1165
- grid3: {
1166
- commandId,
1167
- parameters: { text: insertText },
1169
+ if (!semanticAction) {
1170
+ const insertText = getParam('text');
1171
+ semanticAction = {
1172
+ category: treeStructure_1.AACSemanticCategory.COMMUNICATION,
1173
+ intent: treeStructure_1.AACSemanticIntent.SPEAK_IMMEDIATE,
1174
+ text: insertText,
1175
+ platformData: {
1176
+ grid3: {
1177
+ commandId,
1178
+ parameters: { text: insertText },
1179
+ },
1168
1180
  },
1169
- },
1170
- fallback: {
1171
- type: 'SPEAK',
1172
- message: insertText,
1173
- },
1174
- };
1181
+ fallback: {
1182
+ type: 'SPEAK',
1183
+ message: insertText,
1184
+ },
1185
+ };
1186
+ }
1175
1187
  break;
1176
1188
  }
1177
1189
  case 'Prediction.PredictThis': {
@@ -1204,190 +1216,207 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
1204
1216
  // speak
1205
1217
  const speakUnit = getParam('unit');
1206
1218
  const moveCaret = getParam('movecaret');
1207
- semanticAction = {
1208
- category: treeStructure_1.AACSemanticCategory.COMMUNICATION,
1209
- intent: treeStructure_1.AACSemanticIntent.SPEAK_TEXT,
1210
- platformData: {
1211
- grid3: {
1212
- commandId,
1213
- parameters: {
1214
- unit: speakUnit,
1215
- movecaret: moveCaret,
1219
+ if (!semanticAction) {
1220
+ semanticAction = {
1221
+ category: treeStructure_1.AACSemanticCategory.COMMUNICATION,
1222
+ intent: treeStructure_1.AACSemanticIntent.SPEAK_TEXT,
1223
+ platformData: {
1224
+ grid3: {
1225
+ commandId,
1226
+ parameters: {
1227
+ unit: speakUnit,
1228
+ movecaret: moveCaret,
1229
+ },
1216
1230
  },
1217
1231
  },
1218
- },
1219
- fallback: {
1232
+ fallback: {
1233
+ type: 'SPEAK',
1234
+ message: 'Speak text',
1235
+ },
1236
+ };
1237
+ _legacyAction = {
1220
1238
  type: 'SPEAK',
1221
- message: 'Speak text',
1222
- },
1223
- };
1224
- legacyAction = {
1225
- type: 'SPEAK',
1226
- unit: speakUnit,
1227
- moveCaret: moveCaret ? parseInt(String(moveCaret)) : undefined,
1228
- };
1239
+ unit: speakUnit,
1240
+ moveCaret: moveCaret ? parseInt(String(moveCaret)) : undefined,
1241
+ };
1242
+ }
1229
1243
  break;
1230
1244
  }
1231
1245
  case 'Action.InsertText': {
1232
- // speak
1233
1246
  const insertText = getParam('text');
1234
- semanticAction = {
1235
- category: treeStructure_1.AACSemanticCategory.COMMUNICATION,
1236
- intent: treeStructure_1.AACSemanticIntent.INSERT_TEXT,
1237
- text: insertText,
1238
- platformData: {
1239
- grid3: {
1240
- commandId,
1241
- parameters: { text: insertText },
1247
+ const posParam = getParam('pos');
1248
+ // Always extract POS even if semanticAction is already set
1249
+ if (posParam) {
1250
+ buttonPos = posParam;
1251
+ }
1252
+ if (!semanticAction) {
1253
+ semanticAction = {
1254
+ category: treeStructure_1.AACSemanticCategory.COMMUNICATION,
1255
+ intent: treeStructure_1.AACSemanticIntent.INSERT_TEXT,
1256
+ text: insertText,
1257
+ platformData: {
1258
+ grid3: {
1259
+ commandId,
1260
+ parameters: { text: insertText, pos: posParam },
1261
+ },
1242
1262
  },
1243
- },
1244
- fallback: {
1245
- type: 'SPEAK',
1246
- message: insertText,
1247
- },
1248
- };
1249
- legacyAction = {
1250
- type: 'INSERT_TEXT',
1251
- text: insertText,
1252
- };
1263
+ fallback: {
1264
+ type: 'SPEAK',
1265
+ message: insertText,
1266
+ },
1267
+ };
1268
+ _legacyAction = {
1269
+ type: 'INSERT_TEXT',
1270
+ text: insertText,
1271
+ };
1272
+ }
1253
1273
  break;
1254
1274
  }
1255
1275
  case 'Action.DeleteWord':
1256
- // action
1257
- semanticAction = {
1258
- category: treeStructure_1.AACSemanticCategory.TEXT_EDITING,
1259
- intent: treeStructure_1.AACSemanticIntent.DELETE_WORD,
1260
- platformData: {
1261
- grid3: {
1262
- commandId,
1263
- parameters: {},
1276
+ if (!semanticAction) {
1277
+ semanticAction = {
1278
+ category: treeStructure_1.AACSemanticCategory.TEXT_EDITING,
1279
+ intent: treeStructure_1.AACSemanticIntent.DELETE_WORD,
1280
+ platformData: {
1281
+ grid3: {
1282
+ commandId,
1283
+ parameters: {},
1284
+ },
1264
1285
  },
1265
- },
1266
- fallback: {
1267
- type: 'ACTION',
1268
- message: 'Delete word',
1269
- },
1270
- };
1271
- legacyAction = {
1272
- type: 'DELETE_WORD',
1273
- };
1286
+ fallback: {
1287
+ type: 'ACTION',
1288
+ message: 'Delete word',
1289
+ },
1290
+ };
1291
+ _legacyAction = {
1292
+ type: 'DELETE_WORD',
1293
+ };
1294
+ }
1274
1295
  break;
1275
1296
  case 'Action.DeleteLetter':
1276
- // action
1277
- semanticAction = {
1278
- category: treeStructure_1.AACSemanticCategory.TEXT_EDITING,
1279
- intent: treeStructure_1.AACSemanticIntent.DELETE_CHARACTER,
1280
- platformData: {
1281
- grid3: {
1282
- commandId,
1283
- parameters: {},
1297
+ if (!semanticAction) {
1298
+ semanticAction = {
1299
+ category: treeStructure_1.AACSemanticCategory.TEXT_EDITING,
1300
+ intent: treeStructure_1.AACSemanticIntent.DELETE_CHARACTER,
1301
+ platformData: {
1302
+ grid3: {
1303
+ commandId,
1304
+ parameters: {},
1305
+ },
1284
1306
  },
1285
- },
1286
- fallback: {
1287
- type: 'ACTION',
1288
- message: 'Delete character',
1289
- },
1290
- };
1291
- legacyAction = {
1292
- type: 'DELETE_CHARACTER',
1293
- };
1307
+ fallback: {
1308
+ type: 'ACTION',
1309
+ message: 'Delete character',
1310
+ },
1311
+ };
1312
+ _legacyAction = {
1313
+ type: 'DELETE_CHARACTER',
1314
+ };
1315
+ }
1294
1316
  break;
1295
1317
  case 'Action.Clear':
1296
1318
  // action
1297
- semanticAction = {
1298
- category: treeStructure_1.AACSemanticCategory.TEXT_EDITING,
1299
- intent: treeStructure_1.AACSemanticIntent.CLEAR_TEXT,
1300
- platformData: {
1301
- grid3: {
1302
- commandId,
1303
- parameters: {},
1319
+ if (!semanticAction) {
1320
+ semanticAction = {
1321
+ category: treeStructure_1.AACSemanticCategory.TEXT_EDITING,
1322
+ intent: treeStructure_1.AACSemanticIntent.CLEAR_TEXT,
1323
+ platformData: {
1324
+ grid3: {
1325
+ commandId,
1326
+ parameters: {},
1327
+ },
1304
1328
  },
1305
- },
1306
- fallback: {
1307
- type: 'ACTION',
1308
- message: 'Clear text',
1309
- },
1310
- };
1311
- legacyAction = {
1312
- type: 'CLEAR_TEXT',
1313
- };
1329
+ fallback: {
1330
+ type: 'ACTION',
1331
+ message: 'Clear text',
1332
+ },
1333
+ };
1334
+ _legacyAction = {
1335
+ type: 'CLEAR_TEXT',
1336
+ };
1337
+ }
1314
1338
  break;
1315
1339
  case 'Action.Letter': {
1316
1340
  // action
1317
1341
  const letter = getParam('letter');
1318
- semanticAction = {
1319
- category: treeStructure_1.AACSemanticCategory.TEXT_EDITING,
1320
- intent: treeStructure_1.AACSemanticIntent.INSERT_TEXT,
1321
- text: letter,
1322
- platformData: {
1323
- grid3: {
1324
- commandId,
1325
- parameters: { letter },
1342
+ if (!semanticAction) {
1343
+ semanticAction = {
1344
+ category: treeStructure_1.AACSemanticCategory.TEXT_EDITING,
1345
+ intent: treeStructure_1.AACSemanticIntent.INSERT_TEXT,
1346
+ text: letter,
1347
+ platformData: {
1348
+ grid3: {
1349
+ commandId,
1350
+ parameters: { letter },
1351
+ },
1326
1352
  },
1327
- },
1328
- fallback: {
1329
- type: 'ACTION',
1330
- message: letter,
1331
- },
1332
- };
1333
- legacyAction = {
1334
- type: 'INSERT_LETTER',
1335
- letter,
1336
- };
1353
+ fallback: {
1354
+ type: 'ACTION',
1355
+ message: letter,
1356
+ },
1357
+ };
1358
+ _legacyAction = {
1359
+ type: 'INSERT_LETTER',
1360
+ letter,
1361
+ };
1362
+ }
1337
1363
  break;
1338
1364
  }
1339
1365
  case 'Settings.RestAll':
1340
1366
  // action
1341
- semanticAction = {
1342
- category: treeStructure_1.AACSemanticCategory.CUSTOM,
1343
- intent: treeStructure_1.AACSemanticIntent.PLATFORM_SPECIFIC,
1344
- platformData: {
1345
- grid3: {
1346
- commandId,
1347
- parameters: {
1348
- indicatorenabled: getParam('indicatorenabled'),
1349
- action: getParam('action'),
1367
+ if (!semanticAction) {
1368
+ semanticAction = {
1369
+ category: treeStructure_1.AACSemanticCategory.CUSTOM,
1370
+ intent: treeStructure_1.AACSemanticIntent.PLATFORM_SPECIFIC,
1371
+ platformData: {
1372
+ grid3: {
1373
+ commandId,
1374
+ parameters: {
1375
+ indicatorenabled: getParam('indicatorenabled'),
1376
+ action: getParam('action'),
1377
+ },
1350
1378
  },
1351
1379
  },
1352
- },
1353
- fallback: {
1354
- type: 'ACTION',
1355
- message: 'Settings action',
1356
- },
1357
- };
1358
- legacyAction = {
1359
- type: 'SETTINGS',
1360
- indicatorEnabled: getParam('indicatorenabled') === '1',
1361
- settingsAction: getParam('action'),
1362
- };
1380
+ fallback: {
1381
+ type: 'ACTION',
1382
+ message: 'Settings action',
1383
+ },
1384
+ };
1385
+ _legacyAction = {
1386
+ type: 'SETTINGS',
1387
+ indicatorEnabled: getParam('indicatorenabled') === '1',
1388
+ settingsAction: getParam('action'),
1389
+ };
1390
+ }
1363
1391
  break;
1364
1392
  case 'AutoContent.Activate':
1365
1393
  // action
1366
- semanticAction = {
1367
- category: treeStructure_1.AACSemanticCategory.CUSTOM,
1368
- intent: treeStructure_1.AACSemanticIntent.PLATFORM_SPECIFIC,
1369
- platformData: {
1370
- grid3: {
1371
- commandId,
1372
- parameters: {
1373
- autocontenttype: getParam('autocontenttype'),
1394
+ if (!semanticAction) {
1395
+ semanticAction = {
1396
+ category: treeStructure_1.AACSemanticCategory.CUSTOM,
1397
+ intent: treeStructure_1.AACSemanticIntent.PLATFORM_SPECIFIC,
1398
+ platformData: {
1399
+ grid3: {
1400
+ commandId,
1401
+ parameters: {
1402
+ autocontenttype: getParam('autocontenttype'),
1403
+ },
1374
1404
  },
1375
1405
  },
1376
- },
1377
- fallback: {
1378
- type: 'ACTION',
1379
- message: 'Auto content',
1380
- },
1381
- };
1382
- legacyAction = {
1383
- type: 'AUTO_CONTENT',
1384
- autoContentType: getParam('autocontenttype'),
1385
- };
1406
+ fallback: {
1407
+ type: 'ACTION',
1408
+ message: 'Auto content',
1409
+ },
1410
+ };
1411
+ _legacyAction = {
1412
+ type: 'AUTO_CONTENT',
1413
+ autoContentType: getParam('autocontenttype'),
1414
+ };
1415
+ }
1386
1416
  break;
1387
1417
  default:
1388
1418
  // Unknown command - preserve as generic action
1389
- if (commandId) {
1390
- // action
1419
+ if (commandId && !semanticAction) {
1391
1420
  const allParams = Object.fromEntries(paramArr.map((p) => [p.Key || p.key, p['#text']]));
1392
1421
  semanticAction = {
1393
1422
  category: treeStructure_1.AACSemanticCategory.CUSTOM,
@@ -1403,16 +1432,13 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
1403
1432
  message: 'Unknown command',
1404
1433
  },
1405
1434
  };
1406
- legacyAction = {
1407
- type: 'SPEAK',
1408
- parameters: { commandId, ...allParams },
1409
- };
1435
+ // legacy action not needed for unknown commands
1410
1436
  }
1411
1437
  break;
1412
1438
  }
1413
- // Use first recognized command
1414
- if (semanticAction || legacyAction)
1415
- break;
1439
+ // Continue processing remaining commands so that navigation
1440
+ // targets (Jump.To) are discovered even when a non-navigation
1441
+ // command (e.g. Jump.SetBookmark, Action.InsertText) appears first.
1416
1442
  }
1417
1443
  }
1418
1444
  // Create default semantic action if none was created from commands
@@ -1457,8 +1483,10 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
1457
1483
  }
1458
1484
  // Extract grammar tags from commands (Smart Grammar)
1459
1485
  const grammar = {};
1486
+ if (buttonPos)
1487
+ grammar.pos = buttonPos;
1460
1488
  detectedCommands.forEach((cmd) => {
1461
- if (cmd.parameters.pos)
1489
+ if (!grammar.pos && cmd.parameters.pos)
1462
1490
  grammar.pos = cmd.parameters.pos;
1463
1491
  if (cmd.parameters.person)
1464
1492
  grammar.person = cmd.parameters.person;
@@ -1468,6 +1496,7 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
1468
1496
  grammar.feature = cmd.parameters.feature;
1469
1497
  });
1470
1498
  const isSmartGrammarCell = Object.keys(grammar).length > 0;
1499
+ const effectivePos = buttonPos || grammar.pos || undefined;
1471
1500
  const button = new treeStructure_1.AACButton({
1472
1501
  id: `${gridId}_btn_${idx}`,
1473
1502
  label: String(label),
@@ -1505,6 +1534,7 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
1505
1534
  : gridPredictionWords.length > 0
1506
1535
  ? [...gridPredictionWords]
1507
1536
  : undefined,
1537
+ pos: effectivePos,
1508
1538
  parameters: {
1509
1539
  pluginMetadata: pluginMetadata, // Store full plugin metadata for future use
1510
1540
  grid3Commands: detectedCommands, // Store detected command metadata
@@ -1676,7 +1706,7 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
1676
1706
  }
1677
1707
  }
1678
1708
  }
1679
- catch (e) {
1709
+ catch (_e) {
1680
1710
  // If settings.xml parsing fails, tree.rootId will default to first page
1681
1711
  }
1682
1712
  // Set metadata on tree