@willwade/aac-processors 0.0.23 → 0.0.25
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.
|
@@ -561,7 +561,9 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
561
561
|
for (let r = 0; r < maxRows; r++) {
|
|
562
562
|
gridLayout[r] = new Array(maxCols).fill(null);
|
|
563
563
|
}
|
|
564
|
-
|
|
564
|
+
// Track grid-level prediction wordlists so we can attach them to AutoContent
|
|
565
|
+
const gridPredictionWords = [];
|
|
566
|
+
let predictionCellCounter = 0;
|
|
565
567
|
// Extract words from grid-level AutoContentCommands (e.g., Prediction Bar)
|
|
566
568
|
if (grid.AutoContentCommands) {
|
|
567
569
|
const collections = grid.AutoContentCommands.AutoContentCommandCollection;
|
|
@@ -581,7 +583,7 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
581
583
|
const wordListParam = paramArr.find((p) => (p['@_Key'] || p.Key || p.key) === 'wordlist');
|
|
582
584
|
if (wordListParam) {
|
|
583
585
|
const words = this._extractWordsFromWordList(wordListParam);
|
|
584
|
-
|
|
586
|
+
gridPredictionWords.push(...words);
|
|
585
587
|
}
|
|
586
588
|
}
|
|
587
589
|
});
|
|
@@ -657,6 +659,22 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
657
659
|
const message = label; // Use caption as message
|
|
658
660
|
// Detect plugin cell type (Workspace, LiveCell, AutoContent)
|
|
659
661
|
const pluginMetadata = (0, pluginTypes_1.detectPluginCellType)(content);
|
|
662
|
+
// Friendly labels for workspace/prediction cells when captions are missing
|
|
663
|
+
if (pluginMetadata.cellType === pluginTypes_1.Grid3CellType.Workspace) {
|
|
664
|
+
if (!label || label.startsWith('Cell_')) {
|
|
665
|
+
label =
|
|
666
|
+
pluginMetadata.displayName ||
|
|
667
|
+
pluginMetadata.subType ||
|
|
668
|
+
pluginMetadata.pluginId ||
|
|
669
|
+
'Workspace';
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
if (pluginMetadata.cellType === pluginTypes_1.Grid3CellType.AutoContent &&
|
|
673
|
+
pluginMetadata.autoContentType === 'Prediction') {
|
|
674
|
+
predictionCellCounter += 1;
|
|
675
|
+
// Always surface a friendly label for predictions even if a placeholder exists
|
|
676
|
+
label = `Prediction ${predictionCellCounter}`;
|
|
677
|
+
}
|
|
660
678
|
// Parse all command types from Grid3 and create semantic actions
|
|
661
679
|
let semanticAction;
|
|
662
680
|
let legacyAction = null;
|
|
@@ -664,6 +682,7 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
664
682
|
let navigationTarget;
|
|
665
683
|
let detectedCommands = []; // Store detected command metadata
|
|
666
684
|
const commands = content.Commands?.Command || content.commands?.command;
|
|
685
|
+
let predictionWords;
|
|
667
686
|
// Resolve image for this cell using FileMap and coordinate heuristics
|
|
668
687
|
const imageCandidate = captionAndImage?.Image ||
|
|
669
688
|
captionAndImage?.image ||
|
|
@@ -705,7 +724,9 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
705
724
|
}
|
|
706
725
|
if (wlP) {
|
|
707
726
|
const words = this._extractWordsFromWordList(wlP);
|
|
708
|
-
words.
|
|
727
|
+
if (words.length > 0) {
|
|
728
|
+
predictionWords = words;
|
|
729
|
+
}
|
|
709
730
|
}
|
|
710
731
|
}
|
|
711
732
|
});
|
|
@@ -746,20 +767,21 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
746
767
|
// Skip PredictThis in primary action loop as it was handled in pre-pass
|
|
747
768
|
// unless we need a primary action and nothing else exists
|
|
748
769
|
if (commandId === 'Prediction.PredictThis') {
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
}
|
|
762
|
-
|
|
770
|
+
const wlParam = getRawParam('wordlist');
|
|
771
|
+
const words = wlParam ? this._extractWordsFromWordList(wlParam) : [];
|
|
772
|
+
if (words.length > 0) {
|
|
773
|
+
predictionWords = words;
|
|
774
|
+
}
|
|
775
|
+
if (!semanticAction && words.length > 0) {
|
|
776
|
+
semanticAction = {
|
|
777
|
+
category: treeStructure_1.AACSemanticCategory.COMMUNICATION,
|
|
778
|
+
intent: treeStructure_1.AACSemanticIntent.PLATFORM_SPECIFIC,
|
|
779
|
+
text: words.slice(0, 3).join(', '),
|
|
780
|
+
platformData: {
|
|
781
|
+
grid3: { commandId, parameters: { wordlist: words } },
|
|
782
|
+
},
|
|
783
|
+
fallback: { type: 'ACTION', message: 'Predict words' },
|
|
784
|
+
};
|
|
763
785
|
}
|
|
764
786
|
continue;
|
|
765
787
|
}
|
|
@@ -881,13 +903,9 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
881
903
|
}
|
|
882
904
|
case 'Prediction.PredictThis': {
|
|
883
905
|
const wlParam = getRawParam('wordlist');
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
words.forEach((w) => pagePredictedWords.add(w));
|
|
888
|
-
// Store words in a way that analyzer can find them
|
|
889
|
-
// For now, we'll attach to semanticAction so it can be used later
|
|
890
|
-
// We only set this as the primary action if we don't have one yet
|
|
906
|
+
const words = wlParam ? this._extractWordsFromWordList(wlParam) : [];
|
|
907
|
+
if (words.length > 0) {
|
|
908
|
+
predictionWords = words;
|
|
891
909
|
if (!semanticAction) {
|
|
892
910
|
semanticAction = {
|
|
893
911
|
category: treeStructure_1.AACSemanticCategory.COMMUNICATION,
|
|
@@ -1214,6 +1232,15 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
1214
1232
|
symbolLibraryRef: symbolLibraryRef, // Store full symbol reference
|
|
1215
1233
|
grammar: isSmartGrammarCell ? grammar : undefined,
|
|
1216
1234
|
isSmartGrammarCell: isSmartGrammarCell,
|
|
1235
|
+
predictions: predictionWords?.length
|
|
1236
|
+
? [...predictionWords]
|
|
1237
|
+
: gridPredictionWords.length > 0
|
|
1238
|
+
? [...gridPredictionWords]
|
|
1239
|
+
: undefined,
|
|
1240
|
+
predictionSlot: pluginMetadata.cellType === pluginTypes_1.Grid3CellType.AutoContent &&
|
|
1241
|
+
pluginMetadata.autoContentType === 'Prediction'
|
|
1242
|
+
? predictionCellCounter
|
|
1243
|
+
: undefined,
|
|
1217
1244
|
},
|
|
1218
1245
|
});
|
|
1219
1246
|
// Add button to page
|
|
@@ -1227,59 +1254,6 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
1227
1254
|
}
|
|
1228
1255
|
}
|
|
1229
1256
|
});
|
|
1230
|
-
// Process predicted words: Populate AutoContent slots first, then add virtual buttons at bottom
|
|
1231
|
-
if (pagePredictedWords.size > 0) {
|
|
1232
|
-
const extraWords = Array.from(pagePredictedWords).filter((w) => w.trim().length > 0);
|
|
1233
|
-
if (extraWords.length > 0) {
|
|
1234
|
-
let wordIdx = 0;
|
|
1235
|
-
// Step 1: Fill dedicated AutoContent prediction slots (e.g. at the top)
|
|
1236
|
-
page.buttons.forEach((btn) => {
|
|
1237
|
-
if (btn.contentType === 'AutoContent' &&
|
|
1238
|
-
btn.contentSubType === 'Prediction' &&
|
|
1239
|
-
wordIdx < extraWords.length) {
|
|
1240
|
-
const word = extraWords[wordIdx++];
|
|
1241
|
-
btn.label = word;
|
|
1242
|
-
btn.message = word;
|
|
1243
|
-
btn.semanticAction = {
|
|
1244
|
-
category: treeStructure_1.AACSemanticCategory.COMMUNICATION,
|
|
1245
|
-
intent: treeStructure_1.AACSemanticIntent.INSERT_TEXT,
|
|
1246
|
-
text: word,
|
|
1247
|
-
fallback: { type: 'SPEAK', message: word },
|
|
1248
|
-
};
|
|
1249
|
-
}
|
|
1250
|
-
});
|
|
1251
|
-
// Step 2: Add remaining words as virtual buttons at the bottom
|
|
1252
|
-
if (wordIdx < extraWords.length) {
|
|
1253
|
-
const remainingWords = extraWords.slice(wordIdx);
|
|
1254
|
-
const extraRowsCount = Math.ceil(remainingWords.length / maxCols);
|
|
1255
|
-
for (let r = 0; r < extraRowsCount; r++) {
|
|
1256
|
-
const row = new Array(maxCols).fill(null);
|
|
1257
|
-
for (let c = 0; c < maxCols; c++) {
|
|
1258
|
-
const idx = r * maxCols + c;
|
|
1259
|
-
if (idx < remainingWords.length) {
|
|
1260
|
-
const word = remainingWords[idx];
|
|
1261
|
-
const vBtn = new treeStructure_1.AACButton({
|
|
1262
|
-
id: `${gridId}_vpredict_${wordIdx + idx}`,
|
|
1263
|
-
label: word,
|
|
1264
|
-
message: word,
|
|
1265
|
-
x: c,
|
|
1266
|
-
y: maxRows + r,
|
|
1267
|
-
semanticAction: {
|
|
1268
|
-
category: treeStructure_1.AACSemanticCategory.COMMUNICATION,
|
|
1269
|
-
intent: treeStructure_1.AACSemanticIntent.INSERT_TEXT,
|
|
1270
|
-
text: word,
|
|
1271
|
-
fallback: { type: 'SPEAK', message: word },
|
|
1272
|
-
},
|
|
1273
|
-
});
|
|
1274
|
-
row[c] = vBtn;
|
|
1275
|
-
page.addButton(vBtn);
|
|
1276
|
-
}
|
|
1277
|
-
}
|
|
1278
|
-
gridLayout.push(row);
|
|
1279
|
-
}
|
|
1280
|
-
}
|
|
1281
|
-
}
|
|
1282
|
-
}
|
|
1283
1257
|
// Set the page's grid layout
|
|
1284
1258
|
page.grid = gridLayout;
|
|
1285
1259
|
// Generate clone_id for each button in the grid
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@willwade/aac-processors",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.25",
|
|
4
4
|
"description": "A comprehensive TypeScript library for processing AAC (Augmentative and Alternative Communication) file formats with translation support",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|