@willwade/aac-processors 0.2.19 → 0.2.20

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.
@@ -131,6 +131,14 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
131
131
  generateCommandsFromSemanticAction(button, tree) {
132
132
  const semanticAction = button.semanticAction;
133
133
  if (!semanticAction) {
134
+ // Workspace and LiveCell cells should have no commands
135
+ if (button.contentType === 'Workspace' || button.contentType === 'LiveCell') {
136
+ return '';
137
+ }
138
+ // AutoContent cells may or may not have commands
139
+ if (button.contentType === 'AutoContent') {
140
+ return '';
141
+ }
134
142
  // Default to insert text action with structured XML format
135
143
  // Use two <s> elements: one for the word, one for the space (CDATA preserves whitespace)
136
144
  let text = button.message || button.label || '';
@@ -277,10 +285,10 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
277
285
  };
278
286
  }
279
287
  default: {
280
- // Use two <s> elements: one for the word, one for the space (CDATA preserves whitespace)
281
- // Fallback to insert text with structured XML format
288
+ if (semanticAction.platformData?.grid3) {
289
+ break;
290
+ }
282
291
  let text = semanticAction.text || button.message || button.label || '';
283
- // Remove trailing space from message if present (we'll add it as separate segment)
284
292
  if (text.endsWith(' ')) {
285
293
  text = text.slice(0, -1);
286
294
  }
@@ -1415,7 +1423,6 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
1415
1423
  }
1416
1424
  break;
1417
1425
  case 'AutoContent.Activate':
1418
- // action
1419
1426
  if (!semanticAction) {
1420
1427
  semanticAction = {
1421
1428
  category: treeStructure_1.AACSemanticCategory.CUSTOM,
@@ -1439,8 +1446,819 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
1439
1446
  };
1440
1447
  }
1441
1448
  break;
1449
+ // --- Navigation extras ---
1450
+ case 'Jump.SetBookmark':
1451
+ case 'Jump.Favorite':
1452
+ if (!semanticAction) {
1453
+ const params = {};
1454
+ const fav = getParam('favorite');
1455
+ if (fav)
1456
+ params.favorite = fav;
1457
+ const act = getParam('action');
1458
+ if (act)
1459
+ params.action = act;
1460
+ const ind = getParam('indicatorenabled');
1461
+ if (ind)
1462
+ params.indicatorenabled = ind;
1463
+ semanticAction = {
1464
+ category: treeStructure_1.AACSemanticCategory.NAVIGATION,
1465
+ intent: commandId === 'Jump.SetBookmark'
1466
+ ? treeStructure_1.AACSemanticIntent.TOGGLE_STATE
1467
+ : treeStructure_1.AACSemanticIntent.NAVIGATE_TO,
1468
+ platformData: { grid3: { commandId, parameters: params } },
1469
+ fallback: {
1470
+ type: 'ACTION',
1471
+ message: commandId === 'Jump.SetBookmark'
1472
+ ? 'Toggle bookmark'
1473
+ : 'Jump to favorite',
1474
+ },
1475
+ };
1476
+ }
1477
+ break;
1478
+ // --- Text input / keyboard ---
1479
+ case 'Action.Space':
1480
+ if (!semanticAction) {
1481
+ semanticAction = {
1482
+ category: treeStructure_1.AACSemanticCategory.TEXT_EDITING,
1483
+ intent: treeStructure_1.AACSemanticIntent.INSERT_TEXT,
1484
+ text: ' ',
1485
+ platformData: { grid3: { commandId, parameters: {} } },
1486
+ fallback: { type: 'ACTION', message: 'Space' },
1487
+ };
1488
+ }
1489
+ break;
1490
+ case 'Action.Enter':
1491
+ if (!semanticAction) {
1492
+ semanticAction = {
1493
+ category: treeStructure_1.AACSemanticCategory.TEXT_EDITING,
1494
+ intent: treeStructure_1.AACSemanticIntent.INSERT_TEXT,
1495
+ text: '\n',
1496
+ platformData: { grid3: { commandId, parameters: {} } },
1497
+ fallback: { type: 'ACTION', message: 'Enter' },
1498
+ };
1499
+ }
1500
+ break;
1501
+ case 'Action.Number':
1502
+ case 'Action.Punctuation': {
1503
+ const ch = getParam('letter');
1504
+ if (!semanticAction) {
1505
+ semanticAction = {
1506
+ category: treeStructure_1.AACSemanticCategory.TEXT_EDITING,
1507
+ intent: treeStructure_1.AACSemanticIntent.INSERT_TEXT,
1508
+ text: ch,
1509
+ platformData: { grid3: { commandId, parameters: { letter: ch } } },
1510
+ fallback: { type: 'ACTION', message: ch },
1511
+ };
1512
+ }
1513
+ break;
1514
+ }
1515
+ case 'Action.Backspace':
1516
+ if (!semanticAction) {
1517
+ semanticAction = {
1518
+ category: treeStructure_1.AACSemanticCategory.TEXT_EDITING,
1519
+ intent: treeStructure_1.AACSemanticIntent.DELETE_CHARACTER,
1520
+ platformData: { grid3: { commandId, parameters: {} } },
1521
+ fallback: { type: 'ACTION', message: 'Backspace' },
1522
+ };
1523
+ }
1524
+ break;
1525
+ case 'Action.Copy':
1526
+ if (!semanticAction) {
1527
+ semanticAction = {
1528
+ category: treeStructure_1.AACSemanticCategory.TEXT_EDITING,
1529
+ intent: treeStructure_1.AACSemanticIntent.COPY_TEXT,
1530
+ platformData: { grid3: { commandId, parameters: {} } },
1531
+ fallback: { type: 'ACTION', message: 'Copy' },
1532
+ };
1533
+ }
1534
+ break;
1535
+ case 'Action.Paste':
1536
+ if (!semanticAction) {
1537
+ semanticAction = {
1538
+ category: treeStructure_1.AACSemanticCategory.TEXT_EDITING,
1539
+ intent: treeStructure_1.AACSemanticIntent.PASTE_TEXT,
1540
+ platformData: { grid3: { commandId, parameters: {} } },
1541
+ fallback: { type: 'ACTION', message: 'Paste' },
1542
+ };
1543
+ }
1544
+ break;
1545
+ case 'Action.SelectAll':
1546
+ if (!semanticAction) {
1547
+ semanticAction = {
1548
+ category: treeStructure_1.AACSemanticCategory.TEXT_EDITING,
1549
+ intent: treeStructure_1.AACSemanticIntent.SELECT_ALL,
1550
+ platformData: { grid3: { commandId, parameters: {} } },
1551
+ fallback: { type: 'ACTION', message: 'Select all' },
1552
+ };
1553
+ }
1554
+ break;
1555
+ case 'Action.NextLetter':
1556
+ case 'Action.PreviousLetter':
1557
+ case 'Action.NextWord':
1558
+ case 'Action.PreviousWord':
1559
+ case 'Action.DocumentStart':
1560
+ case 'Action.DocumentEnd': {
1561
+ const dirMap = {
1562
+ 'Action.NextLetter': 'next_letter',
1563
+ 'Action.PreviousLetter': 'previous_letter',
1564
+ 'Action.NextWord': 'next_word',
1565
+ 'Action.PreviousWord': 'previous_word',
1566
+ 'Action.DocumentStart': 'document_start',
1567
+ 'Action.DocumentEnd': 'document_end',
1568
+ };
1569
+ if (!semanticAction) {
1570
+ semanticAction = {
1571
+ category: treeStructure_1.AACSemanticCategory.TEXT_EDITING,
1572
+ intent: treeStructure_1.AACSemanticIntent.CURSOR_MOVE,
1573
+ parameters: { direction: dirMap[commandId] },
1574
+ platformData: { grid3: { commandId, parameters: {} } },
1575
+ fallback: {
1576
+ type: 'ACTION',
1577
+ message: `Cursor ${dirMap[commandId].replace('_', ' ')}`,
1578
+ },
1579
+ };
1580
+ }
1581
+ break;
1582
+ }
1583
+ case 'Action.UndoWorkspaceEdit':
1584
+ case 'Action.UndoClear':
1585
+ if (!semanticAction) {
1586
+ semanticAction = {
1587
+ category: treeStructure_1.AACSemanticCategory.TEXT_EDITING,
1588
+ intent: treeStructure_1.AACSemanticIntent.UNDO,
1589
+ platformData: { grid3: { commandId, parameters: {} } },
1590
+ fallback: { type: 'ACTION', message: 'Undo' },
1591
+ };
1592
+ }
1593
+ break;
1594
+ case 'Action.Print':
1595
+ if (!semanticAction) {
1596
+ semanticAction = {
1597
+ category: treeStructure_1.AACSemanticCategory.TEXT_EDITING,
1598
+ intent: treeStructure_1.AACSemanticIntent.PRINT,
1599
+ platformData: { grid3: { commandId, parameters: {} } },
1600
+ fallback: { type: 'ACTION', message: 'Print' },
1601
+ };
1602
+ }
1603
+ break;
1604
+ case 'Action.SpeakNothing':
1605
+ if (!semanticAction) {
1606
+ semanticAction = {
1607
+ category: treeStructure_1.AACSemanticCategory.COMMUNICATION,
1608
+ intent: treeStructure_1.AACSemanticIntent.SPEAK_TEXT,
1609
+ platformData: { grid3: { commandId, parameters: {} } },
1610
+ fallback: { type: 'SPEAK', message: 'Speak' },
1611
+ };
1612
+ }
1613
+ break;
1614
+ // --- Speech ---
1615
+ case 'Speech.Stop':
1616
+ if (!semanticAction) {
1617
+ semanticAction = {
1618
+ category: treeStructure_1.AACSemanticCategory.COMMUNICATION,
1619
+ intent: treeStructure_1.AACSemanticIntent.STOP_SPEECH,
1620
+ platformData: { grid3: { commandId, parameters: {} } },
1621
+ fallback: { type: 'ACTION', message: 'Stop speech' },
1622
+ };
1623
+ }
1624
+ break;
1625
+ case 'SpeechPlaySound': {
1626
+ const soundFile = getParam('filedata');
1627
+ const waitSound = getParam('wait');
1628
+ if (!semanticAction) {
1629
+ semanticAction = {
1630
+ category: treeStructure_1.AACSemanticCategory.MEDIA,
1631
+ intent: treeStructure_1.AACSemanticIntent.PLAY_SOUND,
1632
+ parameters: { wait: waitSound },
1633
+ platformData: {
1634
+ grid3: {
1635
+ commandId,
1636
+ parameters: { filedata: soundFile, wait: waitSound },
1637
+ },
1638
+ },
1639
+ fallback: { type: 'ACTION', message: 'Play sound' },
1640
+ };
1641
+ }
1642
+ break;
1643
+ }
1644
+ case 'Speech.ChangePublicVoice':
1645
+ case 'Speech.ChangePublicSpeed':
1646
+ case 'Speech.ChangePublicPitch':
1647
+ case 'Speech.ChangePublicVolume':
1648
+ if (!semanticAction) {
1649
+ const speechParams = {};
1650
+ for (const p of paramArr) {
1651
+ const k = p['@_Key'] || p.Key || p.key;
1652
+ if (k)
1653
+ speechParams[k] = p['#text'] ?? p.text;
1654
+ }
1655
+ semanticAction = {
1656
+ category: treeStructure_1.AACSemanticCategory.ACCESSIBILITY,
1657
+ intent: treeStructure_1.AACSemanticIntent.PLATFORM_SPECIFIC,
1658
+ platformData: { grid3: { commandId, parameters: speechParams } },
1659
+ fallback: {
1660
+ type: 'ACTION',
1661
+ message: `Change ${commandId.split('.').pop()}`,
1662
+ },
1663
+ };
1664
+ }
1665
+ break;
1666
+ // --- Computer Control ---
1667
+ case 'ComputerControl.Keyboard': {
1668
+ const keystring = getParam('keystring');
1669
+ if (!semanticAction) {
1670
+ semanticAction = {
1671
+ category: treeStructure_1.AACSemanticCategory.SYSTEM_CONTROL,
1672
+ intent: treeStructure_1.AACSemanticIntent.SEND_KEYS,
1673
+ text: keystring,
1674
+ platformData: { grid3: { commandId, parameters: { keystring } } },
1675
+ fallback: { type: 'ACTION', message: `Send keys: ${keystring}` },
1676
+ };
1677
+ }
1678
+ break;
1679
+ }
1680
+ case 'ComputerControl.SendKeys': {
1681
+ const keys = getParam('keys');
1682
+ if (!semanticAction) {
1683
+ semanticAction = {
1684
+ category: treeStructure_1.AACSemanticCategory.SYSTEM_CONTROL,
1685
+ intent: treeStructure_1.AACSemanticIntent.SEND_KEYS,
1686
+ text: keys,
1687
+ platformData: { grid3: { commandId, parameters: { keys } } },
1688
+ fallback: { type: 'ACTION', message: `Send keys: ${keys}` },
1689
+ };
1690
+ }
1691
+ break;
1692
+ }
1693
+ case 'ComputerControl.LeftClick':
1694
+ case 'ComputerControl.RightClick':
1695
+ case 'ComputerControl.DoubleClick':
1696
+ case 'Mouse.LeftClick':
1697
+ case 'Mouse.RightClick':
1698
+ case 'Mouse.DoubleClick':
1699
+ if (!semanticAction) {
1700
+ semanticAction = {
1701
+ category: treeStructure_1.AACSemanticCategory.SYSTEM_CONTROL,
1702
+ intent: treeStructure_1.AACSemanticIntent.MOUSE_CLICK,
1703
+ parameters: {
1704
+ clickType: commandId.includes('Right')
1705
+ ? 'right'
1706
+ : commandId.includes('Double')
1707
+ ? 'double'
1708
+ : 'left',
1709
+ },
1710
+ platformData: { grid3: { commandId, parameters: {} } },
1711
+ fallback: { type: 'ACTION', message: commandId.split('.').pop() },
1712
+ };
1713
+ }
1714
+ break;
1715
+ case 'ComputerControl.MouseMove':
1716
+ case 'Mouse.Move': {
1717
+ const mx = getParam('x');
1718
+ const my = getParam('y');
1719
+ if (!semanticAction) {
1720
+ semanticAction = {
1721
+ category: treeStructure_1.AACSemanticCategory.SYSTEM_CONTROL,
1722
+ intent: treeStructure_1.AACSemanticIntent.MOUSE_CLICK,
1723
+ parameters: { action: 'move', x: mx, y: my },
1724
+ platformData: { grid3: { commandId, parameters: { x: mx, y: my } } },
1725
+ fallback: { type: 'ACTION', message: 'Move mouse' },
1726
+ };
1727
+ }
1728
+ break;
1729
+ }
1730
+ case 'ComputerControl.WindowsKey':
1731
+ case 'ComputerControl.MenuKey':
1732
+ if (!semanticAction) {
1733
+ semanticAction = {
1734
+ category: treeStructure_1.AACSemanticCategory.SYSTEM_CONTROL,
1735
+ intent: treeStructure_1.AACSemanticIntent.SEND_KEYS,
1736
+ platformData: { grid3: { commandId, parameters: {} } },
1737
+ fallback: { type: 'ACTION', message: commandId.split('.').pop() },
1738
+ };
1739
+ }
1740
+ break;
1741
+ case 'ComputerControl.Shift':
1742
+ if (!semanticAction) {
1743
+ semanticAction = {
1744
+ category: treeStructure_1.AACSemanticCategory.SYSTEM_CONTROL,
1745
+ intent: treeStructure_1.AACSemanticIntent.TOGGLE_STATE,
1746
+ parameters: { target: 'shift', action: getParam('action') },
1747
+ platformData: {
1748
+ grid3: { commandId, parameters: { action: getParam('action') } },
1749
+ },
1750
+ fallback: { type: 'ACTION', message: 'Toggle shift' },
1751
+ };
1752
+ }
1753
+ break;
1754
+ case 'ComputerControl.DeviceMute':
1755
+ if (!semanticAction) {
1756
+ semanticAction = {
1757
+ category: treeStructure_1.AACSemanticCategory.SYSTEM_CONTROL,
1758
+ intent: treeStructure_1.AACSemanticIntent.DEVICE_MUTE,
1759
+ platformData: {
1760
+ grid3: {
1761
+ commandId,
1762
+ parameters: { indicatorenabled: getParam('indicatorenabled') },
1763
+ },
1764
+ },
1765
+ fallback: { type: 'ACTION', message: 'Mute device' },
1766
+ };
1767
+ }
1768
+ break;
1769
+ // --- Web Browser ---
1770
+ case 'WebBrowser.Navigate':
1771
+ case 'WebBrowser.NavigateUrl': {
1772
+ const url = getParam('url');
1773
+ if (!semanticAction) {
1774
+ semanticAction = {
1775
+ category: treeStructure_1.AACSemanticCategory.SYSTEM_CONTROL,
1776
+ intent: treeStructure_1.AACSemanticIntent.WEB_NAVIGATE,
1777
+ text: url,
1778
+ platformData: { grid3: { commandId, parameters: { url } } },
1779
+ fallback: {
1780
+ type: 'ACTION',
1781
+ message: url ? `Navigate to ${url}` : 'Navigate',
1782
+ },
1783
+ };
1784
+ }
1785
+ break;
1786
+ }
1787
+ case 'WebBrowser.Back':
1788
+ case 'WebBrowser.Forward':
1789
+ case 'WebBrowser.Refresh':
1790
+ case 'WebBrowser.Reload':
1791
+ case 'WebBrowser.Stop':
1792
+ case 'WebBrowser.Home':
1793
+ case 'WebAddress.Go':
1794
+ if (!semanticAction) {
1795
+ const webActionLabels = {
1796
+ 'WebBrowser.Back': 'Back',
1797
+ 'WebBrowser.Forward': 'Forward',
1798
+ 'WebBrowser.Refresh': 'Refresh',
1799
+ 'WebBrowser.Reload': 'Reload',
1800
+ 'WebBrowser.Stop': 'Stop loading',
1801
+ 'WebBrowser.Home': 'Home',
1802
+ 'WebAddress.Go': 'Go to address',
1803
+ };
1804
+ semanticAction = {
1805
+ category: treeStructure_1.AACSemanticCategory.SYSTEM_CONTROL,
1806
+ intent: treeStructure_1.AACSemanticIntent.WEB_NAVIGATE,
1807
+ parameters: { webAction: commandId },
1808
+ platformData: { grid3: { commandId, parameters: {} } },
1809
+ fallback: {
1810
+ type: 'ACTION',
1811
+ message: webActionLabels[commandId] || commandId,
1812
+ },
1813
+ };
1814
+ }
1815
+ break;
1816
+ case 'WebBrowser.ScrollUp':
1817
+ case 'WebBrowser.ScrollDown':
1818
+ case 'WebBrowser.ScrollLeft':
1819
+ case 'WebBrowser.ScrollRight': {
1820
+ const scrollSize = getParam('size');
1821
+ const scrollDir = commandId.replace('WebBrowser.Scroll', '').toLowerCase();
1822
+ if (!semanticAction) {
1823
+ semanticAction = {
1824
+ category: treeStructure_1.AACSemanticCategory.SYSTEM_CONTROL,
1825
+ intent: treeStructure_1.AACSemanticIntent.WEB_SCROLL,
1826
+ parameters: { direction: scrollDir, size: scrollSize },
1827
+ platformData: { grid3: { commandId, parameters: { size: scrollSize } } },
1828
+ fallback: { type: 'ACTION', message: `Scroll ${scrollDir}` },
1829
+ };
1830
+ }
1831
+ break;
1832
+ }
1833
+ case 'WebBrowser.ZoomIn':
1834
+ case 'WebBrowser.ZoomOut':
1835
+ case 'WebBrowser.SetZoom': {
1836
+ const zoomOption = getParam('option');
1837
+ if (!semanticAction) {
1838
+ semanticAction = {
1839
+ category: treeStructure_1.AACSemanticCategory.SYSTEM_CONTROL,
1840
+ intent: treeStructure_1.AACSemanticIntent.WEB_SCROLL,
1841
+ parameters: {
1842
+ action: 'zoom',
1843
+ option: zoomOption || commandId.replace('WebBrowser.', ''),
1844
+ },
1845
+ platformData: {
1846
+ grid3: {
1847
+ commandId,
1848
+ parameters: zoomOption ? { option: zoomOption } : {},
1849
+ },
1850
+ },
1851
+ fallback: { type: 'ACTION', message: commandId.replace('WebBrowser.', '') },
1852
+ };
1853
+ }
1854
+ break;
1855
+ }
1856
+ case 'WebBrowser.SpatialNavigateUp':
1857
+ case 'WebBrowser.SpatialNavigateDown':
1858
+ case 'WebBrowser.SpatialNavigateLeft':
1859
+ case 'WebBrowser.SpatialNavigateRight':
1860
+ case 'WebBrowser.NextElement':
1861
+ case 'WebBrowser.PreviousElement': {
1862
+ const focusDir = commandId.includes('Spatial')
1863
+ ? commandId.replace('WebBrowser.SpatialNavigate', '').toLowerCase()
1864
+ : commandId === 'WebBrowser.NextElement'
1865
+ ? 'next'
1866
+ : 'previous';
1867
+ if (!semanticAction) {
1868
+ semanticAction = {
1869
+ category: treeStructure_1.AACSemanticCategory.SYSTEM_CONTROL,
1870
+ intent: treeStructure_1.AACSemanticIntent.WEB_FOCUS_ELEMENT,
1871
+ parameters: { direction: focusDir },
1872
+ platformData: { grid3: { commandId, parameters: {} } },
1873
+ fallback: { type: 'ACTION', message: `Focus ${focusDir} element` },
1874
+ };
1875
+ }
1876
+ break;
1877
+ }
1878
+ case 'WebBrowser.ActivateElement':
1879
+ if (!semanticAction) {
1880
+ semanticAction = {
1881
+ category: treeStructure_1.AACSemanticCategory.SYSTEM_CONTROL,
1882
+ intent: treeStructure_1.AACSemanticIntent.WEB_ACTIVATE_ELEMENT,
1883
+ platformData: { grid3: { commandId, parameters: {} } },
1884
+ fallback: { type: 'ACTION', message: 'Activate element' },
1885
+ };
1886
+ }
1887
+ break;
1888
+ case 'WebBrowser.ReadingMode':
1889
+ case 'WebBrowser.InsertMobileSite': {
1890
+ const toggleAction = getParam('action');
1891
+ if (!semanticAction) {
1892
+ semanticAction = {
1893
+ category: treeStructure_1.AACSemanticCategory.SYSTEM_CONTROL,
1894
+ intent: treeStructure_1.AACSemanticIntent.TOGGLE_STATE,
1895
+ parameters: {
1896
+ target: commandId.replace('WebBrowser.', ''),
1897
+ action: toggleAction,
1898
+ },
1899
+ platformData: {
1900
+ grid3: { commandId, parameters: { action: toggleAction } },
1901
+ },
1902
+ fallback: { type: 'ACTION', message: commandId.replace('WebBrowser.', '') },
1903
+ };
1904
+ }
1905
+ break;
1906
+ }
1907
+ case 'WebBrowser.ExecuteJavaScript': {
1908
+ const jsCommandId = getParam('commandid');
1909
+ if (!semanticAction) {
1910
+ semanticAction = {
1911
+ category: treeStructure_1.AACSemanticCategory.SYSTEM_CONTROL,
1912
+ intent: treeStructure_1.AACSemanticIntent.WEB_EXECUTE_SCRIPT,
1913
+ text: jsCommandId,
1914
+ platformData: {
1915
+ grid3: { commandId, parameters: { commandid: jsCommandId } },
1916
+ },
1917
+ fallback: { type: 'ACTION', message: `Execute: ${jsCommandId}` },
1918
+ };
1919
+ }
1920
+ break;
1921
+ }
1922
+ case 'WebBrowser.SpeakJavascriptFunction': {
1923
+ const speakCmdId = getParam('commandid');
1924
+ if (!semanticAction) {
1925
+ semanticAction = {
1926
+ category: treeStructure_1.AACSemanticCategory.SYSTEM_CONTROL,
1927
+ intent: treeStructure_1.AACSemanticIntent.WEB_EXECUTE_SCRIPT,
1928
+ parameters: { speak: true },
1929
+ text: speakCmdId,
1930
+ platformData: {
1931
+ grid3: { commandId, parameters: { commandid: speakCmdId } },
1932
+ },
1933
+ fallback: { type: 'ACTION', message: `Read aloud: ${speakCmdId}` },
1934
+ };
1935
+ }
1936
+ break;
1937
+ }
1938
+ case 'WebBrowser.FavoriteAdd':
1939
+ case 'WebBrowser.InsertFavourite':
1940
+ case 'WebBrowser.DeleteFavourite':
1941
+ case 'WebBrowser.MoreLinks': {
1942
+ const favParams = {};
1943
+ for (const p of paramArr) {
1944
+ const k = p['@_Key'] || p.Key || p.key;
1945
+ if (k)
1946
+ favParams[k] = p['#text'] ?? p.text;
1947
+ }
1948
+ if (!semanticAction) {
1949
+ semanticAction = {
1950
+ category: treeStructure_1.AACSemanticCategory.SYSTEM_CONTROL,
1951
+ intent: treeStructure_1.AACSemanticIntent.WEB_NAVIGATE,
1952
+ parameters: { webAction: commandId },
1953
+ platformData: { grid3: { commandId, parameters: favParams } },
1954
+ fallback: { type: 'ACTION', message: commandId.replace('WebBrowser.', '') },
1955
+ };
1956
+ }
1957
+ break;
1958
+ }
1959
+ // --- Media ---
1960
+ case 'Media.PlayPause':
1961
+ case 'Media.Next':
1962
+ case 'Media.Previous':
1963
+ case 'Media.VolumeUp':
1964
+ case 'Media.VolumeDown':
1965
+ if (!semanticAction) {
1966
+ semanticAction = {
1967
+ category: treeStructure_1.AACSemanticCategory.MEDIA,
1968
+ intent: treeStructure_1.AACSemanticIntent.PLAY_VIDEO,
1969
+ parameters: { mediaAction: commandId.replace('Media.', '') },
1970
+ platformData: { grid3: { commandId, parameters: {} } },
1971
+ fallback: { type: 'ACTION', message: commandId.replace('Media.', '') },
1972
+ };
1973
+ }
1974
+ break;
1975
+ case 'Media.Stop':
1976
+ if (!semanticAction) {
1977
+ semanticAction = {
1978
+ category: treeStructure_1.AACSemanticCategory.MEDIA,
1979
+ intent: treeStructure_1.AACSemanticIntent.STOP_MEDIA,
1980
+ platformData: { grid3: { commandId, parameters: {} } },
1981
+ fallback: { type: 'ACTION', message: 'Stop' },
1982
+ };
1983
+ }
1984
+ break;
1985
+ // --- MusicVideo ---
1986
+ case 'MusicVideo.ListVideos':
1987
+ case 'MusicVideo.MoreMusicVideos':
1988
+ case 'MusicVideo.SetVideoFolder':
1989
+ case 'MusicVideo.Stop':
1990
+ case 'MusicVideo.StoreAsAttachmentCommandId': {
1991
+ const mvParams = {};
1992
+ for (const p of paramArr) {
1993
+ const k = p['@_Key'] || p.Key || p.key;
1994
+ if (k)
1995
+ mvParams[k] = p['#text'] ?? p.text;
1996
+ }
1997
+ if (!semanticAction) {
1998
+ semanticAction = {
1999
+ category: treeStructure_1.AACSemanticCategory.MEDIA,
2000
+ intent: commandId === 'MusicVideo.Stop'
2001
+ ? treeStructure_1.AACSemanticIntent.STOP_MEDIA
2002
+ : treeStructure_1.AACSemanticIntent.PLAY_VIDEO,
2003
+ parameters: mvParams,
2004
+ platformData: { grid3: { commandId, parameters: mvParams } },
2005
+ fallback: { type: 'ACTION', message: commandId.replace('MusicVideo.', '') },
2006
+ };
2007
+ }
2008
+ break;
2009
+ }
2010
+ // --- Photos ---
2011
+ case 'Photos.Snapshot':
2012
+ if (!semanticAction) {
2013
+ semanticAction = {
2014
+ category: treeStructure_1.AACSemanticCategory.MEDIA,
2015
+ intent: treeStructure_1.AACSemanticIntent.TAKE_PHOTO,
2016
+ platformData: { grid3: { commandId, parameters: {} } },
2017
+ fallback: { type: 'ACTION', message: 'Take photo' },
2018
+ };
2019
+ }
2020
+ break;
2021
+ case 'Photos.ChangeCamera':
2022
+ if (!semanticAction) {
2023
+ semanticAction = {
2024
+ category: treeStructure_1.AACSemanticCategory.MEDIA,
2025
+ intent: treeStructure_1.AACSemanticIntent.TOGGLE_STATE,
2026
+ parameters: { target: 'camera' },
2027
+ platformData: {
2028
+ grid3: {
2029
+ commandId,
2030
+ parameters: { indicatorenabled: getParam('indicatorenabled') },
2031
+ },
2032
+ },
2033
+ fallback: { type: 'ACTION', message: 'Change camera' },
2034
+ };
2035
+ }
2036
+ break;
2037
+ case 'Photos.MorePhotos':
2038
+ case 'Photos.MyPictures':
2039
+ case 'Photos.SnapshotsFolder':
2040
+ case 'Photos.StoreAsAttachment':
2041
+ if (!semanticAction) {
2042
+ semanticAction = {
2043
+ category: treeStructure_1.AACSemanticCategory.MEDIA,
2044
+ intent: treeStructure_1.AACSemanticIntent.PLATFORM_SPECIFIC,
2045
+ platformData: { grid3: { commandId, parameters: {} } },
2046
+ fallback: { type: 'ACTION', message: commandId.replace('Photos.', '') },
2047
+ };
2048
+ }
2049
+ break;
2050
+ // --- Command Execution ---
2051
+ case 'CommandExecution.Wait': {
2052
+ const waitTime = getParam('waittime');
2053
+ const cancellable = getParam('cancellable');
2054
+ if (!semanticAction) {
2055
+ semanticAction = {
2056
+ category: treeStructure_1.AACSemanticCategory.SYSTEM_CONTROL,
2057
+ intent: treeStructure_1.AACSemanticIntent.WAIT,
2058
+ parameters: { waittime: waitTime, cancellable },
2059
+ platformData: {
2060
+ grid3: { commandId, parameters: { waittime: waitTime, cancellable } },
2061
+ },
2062
+ fallback: { type: 'ACTION', message: `Wait ${waitTime}` },
2063
+ };
2064
+ }
2065
+ break;
2066
+ }
2067
+ case 'CommandExecution.AutoRepeat': {
2068
+ const repeatCount = getParam('repeatcount');
2069
+ const repeatGap = getParam('repeatgap');
2070
+ if (!semanticAction) {
2071
+ semanticAction = {
2072
+ category: treeStructure_1.AACSemanticCategory.SYSTEM_CONTROL,
2073
+ intent: treeStructure_1.AACSemanticIntent.REPEAT_COMMANDS,
2074
+ parameters: { repeatcount: repeatCount, repeatgap: repeatGap },
2075
+ platformData: {
2076
+ grid3: {
2077
+ commandId,
2078
+ parameters: { repeatcount: repeatCount, repeatgap: repeatGap },
2079
+ },
2080
+ },
2081
+ fallback: { type: 'ACTION', message: `Repeat ${repeatCount} times` },
2082
+ };
2083
+ }
2084
+ break;
2085
+ }
2086
+ // --- Settings ---
2087
+ case 'Settings.GridExplorer':
2088
+ case 'Settings.Open':
2089
+ if (!semanticAction) {
2090
+ semanticAction = {
2091
+ category: treeStructure_1.AACSemanticCategory.SYSTEM_CONTROL,
2092
+ intent: treeStructure_1.AACSemanticIntent.PLATFORM_SPECIFIC,
2093
+ platformData: { grid3: { commandId, parameters: {} } },
2094
+ fallback: { type: 'ACTION', message: commandId.replace('Settings.', '') },
2095
+ };
2096
+ }
2097
+ break;
2098
+ case 'Settings.RequiredFeature': {
2099
+ const feature = getParam('feature');
2100
+ if (!semanticAction) {
2101
+ semanticAction = {
2102
+ category: treeStructure_1.AACSemanticCategory.ACCESSIBILITY,
2103
+ intent: treeStructure_1.AACSemanticIntent.PLATFORM_SPECIFIC,
2104
+ platformData: { grid3: { commandId, parameters: { feature } } },
2105
+ fallback: { type: 'ACTION', message: `Require ${feature}` },
2106
+ };
2107
+ }
2108
+ break;
2109
+ }
2110
+ case 'Scanning.Start':
2111
+ case 'Scanning.Stop':
2112
+ if (!semanticAction) {
2113
+ semanticAction = {
2114
+ category: treeStructure_1.AACSemanticCategory.ACCESSIBILITY,
2115
+ intent: commandId === 'Scanning.Start'
2116
+ ? treeStructure_1.AACSemanticIntent.SCAN_NEXT
2117
+ : treeStructure_1.AACSemanticIntent.SCAN_SELECT,
2118
+ platformData: { grid3: { commandId, parameters: {} } },
2119
+ fallback: { type: 'ACTION', message: commandId.replace('Scanning.', '') },
2120
+ };
2121
+ }
2122
+ break;
2123
+ // --- Auto Content extras ---
2124
+ case 'Prediction.Clear':
2125
+ if (!semanticAction) {
2126
+ semanticAction = {
2127
+ category: treeStructure_1.AACSemanticCategory.TEXT_EDITING,
2128
+ intent: treeStructure_1.AACSemanticIntent.CLEAR_TEXT,
2129
+ platformData: { grid3: { commandId, parameters: {} } },
2130
+ fallback: { type: 'ACTION', message: 'Clear predictions' },
2131
+ };
2132
+ }
2133
+ break;
2134
+ case 'Prediction.AddToWordList':
2135
+ case 'Prediction.DeleteWord':
2136
+ case 'Prediction.MoreWords': {
2137
+ const predParams = {};
2138
+ for (const p of paramArr) {
2139
+ const k = p['@_Key'] || p.Key || p.key;
2140
+ if (k)
2141
+ predParams[k] = p['#text'] ?? p.text;
2142
+ }
2143
+ if (!semanticAction) {
2144
+ semanticAction = {
2145
+ category: treeStructure_1.AACSemanticCategory.CUSTOM,
2146
+ intent: treeStructure_1.AACSemanticIntent.PLATFORM_SPECIFIC,
2147
+ platformData: { grid3: { commandId, parameters: predParams } },
2148
+ fallback: { type: 'ACTION', message: commandId.replace('Prediction.', '') },
2149
+ };
2150
+ }
2151
+ break;
2152
+ }
2153
+ case 'Grammar.Change':
2154
+ if (!semanticAction) {
2155
+ semanticAction = {
2156
+ category: treeStructure_1.AACSemanticCategory.CUSTOM,
2157
+ intent: treeStructure_1.AACSemanticIntent.PLATFORM_SPECIFIC,
2158
+ platformData: {
2159
+ grid3: { commandId, parameters: { context: getParam('context') } },
2160
+ },
2161
+ fallback: { type: 'ACTION', message: 'Change grammar' },
2162
+ };
2163
+ }
2164
+ break;
2165
+ // --- System ---
2166
+ case 'System.LogOff':
2167
+ case 'System.Lock':
2168
+ case 'System.Sleep':
2169
+ case 'System.Restart':
2170
+ case 'System.ShutDown':
2171
+ if (!semanticAction) {
2172
+ semanticAction = {
2173
+ category: treeStructure_1.AACSemanticCategory.SYSTEM_CONTROL,
2174
+ intent: treeStructure_1.AACSemanticIntent.PLATFORM_SPECIFIC,
2175
+ platformData: { grid3: { commandId, parameters: {} } },
2176
+ fallback: { type: 'ACTION', message: commandId.replace('System.', '') },
2177
+ };
2178
+ }
2179
+ break;
2180
+ // --- Window ---
2181
+ case 'Window.Minimize':
2182
+ case 'Window.Maximize':
2183
+ case 'Window.Close':
2184
+ case 'Window.Switch':
2185
+ if (!semanticAction) {
2186
+ semanticAction = {
2187
+ category: treeStructure_1.AACSemanticCategory.SYSTEM_CONTROL,
2188
+ intent: treeStructure_1.AACSemanticIntent.PLATFORM_SPECIFIC,
2189
+ platformData: { grid3: { commandId, parameters: {} } },
2190
+ fallback: { type: 'ACTION', message: commandId.replace('Window.', '') },
2191
+ };
2192
+ }
2193
+ break;
2194
+ // --- Email ---
2195
+ case 'Email.SendTo':
2196
+ case 'Email.AddRecipient':
2197
+ case 'Email.SetSubject':
2198
+ case 'Email.AttachFile': {
2199
+ const emailParams = {};
2200
+ for (const p of paramArr) {
2201
+ const k = p['@_Key'] || p.Key || p.key;
2202
+ if (k)
2203
+ emailParams[k] = p['#text'] ?? p.text;
2204
+ }
2205
+ if (!semanticAction) {
2206
+ semanticAction = {
2207
+ category: treeStructure_1.AACSemanticCategory.SYSTEM_CONTROL,
2208
+ intent: treeStructure_1.AACSemanticIntent.PLATFORM_SPECIFIC,
2209
+ platformData: { grid3: { commandId, parameters: emailParams } },
2210
+ fallback: { type: 'ACTION', message: commandId.replace('Email.', '') },
2211
+ };
2212
+ }
2213
+ break;
2214
+ }
2215
+ // --- Phone ---
2216
+ case 'Phone.Call':
2217
+ case 'Phone.Answer':
2218
+ case 'Phone.Hangup':
2219
+ if (!semanticAction) {
2220
+ semanticAction = {
2221
+ category: treeStructure_1.AACSemanticCategory.SYSTEM_CONTROL,
2222
+ intent: treeStructure_1.AACSemanticIntent.PLATFORM_SPECIFIC,
2223
+ platformData: { grid3: { commandId, parameters: {} } },
2224
+ fallback: { type: 'ACTION', message: commandId.replace('Phone.', '') },
2225
+ };
2226
+ }
2227
+ break;
2228
+ // --- SMS ---
2229
+ case 'Sms.SendTo':
2230
+ case 'Sms.AddRecipient': {
2231
+ const smsParams = {};
2232
+ for (const p of paramArr) {
2233
+ const k = p['@_Key'] || p.Key || p.key;
2234
+ if (k)
2235
+ smsParams[k] = p['#text'] ?? p.text;
2236
+ }
2237
+ if (!semanticAction) {
2238
+ semanticAction = {
2239
+ category: treeStructure_1.AACSemanticCategory.SYSTEM_CONTROL,
2240
+ intent: treeStructure_1.AACSemanticIntent.PLATFORM_SPECIFIC,
2241
+ platformData: { grid3: { commandId, parameters: smsParams } },
2242
+ fallback: { type: 'ACTION', message: commandId.replace('Sms.', '') },
2243
+ };
2244
+ }
2245
+ break;
2246
+ }
2247
+ // --- Environment Control ---
2248
+ case 'EnvControl.Send':
2249
+ case 'EnvControl.Learn':
2250
+ if (!semanticAction) {
2251
+ semanticAction = {
2252
+ category: treeStructure_1.AACSemanticCategory.SYSTEM_CONTROL,
2253
+ intent: treeStructure_1.AACSemanticIntent.PLATFORM_SPECIFIC,
2254
+ platformData: {
2255
+ grid3: { commandId, parameters: { code: getParam('code') } },
2256
+ },
2257
+ fallback: { type: 'ACTION', message: commandId.replace('EnvControl.', '') },
2258
+ };
2259
+ }
2260
+ break;
1442
2261
  default:
1443
- // Unknown command - preserve as generic action
1444
2262
  if (commandId && !semanticAction) {
1445
2263
  const allParams = Object.fromEntries(paramArr.map((p) => [p.Key || p.key, p['#text']]));
1446
2264
  semanticAction = {
@@ -1454,10 +2272,9 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
1454
2272
  },
1455
2273
  fallback: {
1456
2274
  type: 'ACTION',
1457
- message: 'Unknown command',
2275
+ message: commandId,
1458
2276
  },
1459
2277
  };
1460
- // legacy action not needed for unknown commands
1461
2278
  }
1462
2279
  break;
1463
2280
  }
@@ -1984,6 +2801,28 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
1984
2801
  data: settingsXmlContent,
1985
2802
  });
1986
2803
  // Create Settings0/Styles/style.xml if there are styles
2804
+ // Ensure Workspace and Default styles exist when workspace cells are present
2805
+ const hasAnyWorkspace = Object.values(tree.pages).some((p) => p.buttons.some((b) => b.contentType === 'Workspace' || b.contentType === 'LiveCell'));
2806
+ if (hasAnyWorkspace) {
2807
+ if (!uniqueStyles.has('workspace-style')) {
2808
+ uniqueStyles.set('workspace-style', {
2809
+ id: 'Workspace',
2810
+ style: { backgroundColor: '#FFFFFF00', borderColor: '#FFFFFF00', fontColor: '#000000FF' },
2811
+ });
2812
+ }
2813
+ if (!uniqueStyles.has('default-style')) {
2814
+ uniqueStyles.set('default-style', {
2815
+ id: 'Default',
2816
+ style: {
2817
+ backgroundColor: '#D5DBDBFF',
2818
+ borderColor: '#FFFFFFFF',
2819
+ fontColor: '#000000FF',
2820
+ fontFamily: 'Arial',
2821
+ fontSize: 16,
2822
+ },
2823
+ });
2824
+ }
2825
+ }
1987
2826
  if (uniqueStyles.size > 0) {
1988
2827
  const stylesArray = Array.from(uniqueStyles.values()).map(({ id, style }) => {
1989
2828
  const styleObj = {
@@ -2024,9 +2863,11 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
2024
2863
  const gridFilePaths = [];
2025
2864
  // Create a grid for each page
2026
2865
  Object.values(tree.pages).forEach((page) => {
2866
+ const hasComputerControl = page.buttons.some((b) => b.contentType === 'Workspace' && b.contentSubType === 'ComputerControl');
2027
2867
  const gridData = {
2028
2868
  Grid: {
2029
2869
  '@_xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance',
2870
+ ...(hasComputerControl ? { ComputerControl: '1' } : {}),
2030
2871
  GridGuid: page.id,
2031
2872
  // Calculate grid dimensions based on actual layout
2032
2873
  ColumnDefinitions: this.calculateColumnDefinitions(page),
@@ -2038,7 +2879,14 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
2038
2879
  // Regular button cells
2039
2880
  ...this.filterPageButtons(page.buttons).map((button, btnIndex) => {
2040
2881
  const buttonStyleId = button.style ? addStyle(button.style) : '';
2041
- // Find button position in grid layout
2882
+ // Force Workspace/LiveCell/AutoContent cells to use their standard style names
2883
+ const effectiveStyleId = button.contentType === 'Workspace'
2884
+ ? 'Workspace'
2885
+ : button.contentType === 'LiveCell'
2886
+ ? 'Default'
2887
+ : button.contentType === 'AutoContent'
2888
+ ? 'Default'
2889
+ : buttonStyleId; // Find button position in grid layout
2042
2890
  const position = this.findButtonPosition(page, button, btnIndex);
2043
2891
  // Use position directly from tree
2044
2892
  const yOffset = 0;
@@ -2100,25 +2948,34 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
2100
2948
  });
2101
2949
  }
2102
2950
  }
2951
+ const isPluginCell = button.contentType === 'Workspace' ||
2952
+ button.contentType === 'LiveCell' ||
2953
+ button.contentType === 'AutoContent';
2954
+ const cellContent = {
2955
+ ContentType: button.contentType === 'Normal' ? undefined : button.contentType,
2956
+ ContentSubType: button.contentSubType,
2957
+ };
2958
+ const commands = this.generateCommandsFromSemanticAction(button, tree);
2959
+ if (commands) {
2960
+ cellContent.Commands = commands;
2961
+ }
2962
+ if (!isPluginCell) {
2963
+ cellContent.CaptionAndImage = captionAndImage;
2964
+ }
2103
2965
  const cellData = {
2104
2966
  '@_X': position.x + 1, // Grid3 uses 1-based X coordinates
2105
2967
  '@_Y': position.y + yOffset + 1, // Grid3 uses 1-based Y coordinates with workspace offset
2106
2968
  '@_ColumnSpan': position.columnSpan,
2107
2969
  '@_RowSpan': position.rowSpan,
2108
- Content: {
2109
- ContentType: button.contentType === 'Normal' ? undefined : button.contentType,
2110
- ContentSubType: button.contentSubType,
2111
- Commands: this.generateCommandsFromSemanticAction(button, tree),
2112
- CaptionAndImage: captionAndImage,
2113
- },
2970
+ Content: cellContent,
2114
2971
  };
2115
2972
  // Add style reference and inline color overrides if available
2116
2973
  // Some Grid3 versions need inline colors in addition to style references
2117
- if (buttonStyleId || button.style) {
2974
+ if (effectiveStyleId || button.style) {
2118
2975
  const styleObj = {};
2119
2976
  // Add style reference if we have one
2120
- if (buttonStyleId) {
2121
- styleObj.BasedOnStyle = buttonStyleId;
2977
+ if (effectiveStyleId) {
2978
+ styleObj.BasedOnStyle = effectiveStyleId;
2122
2979
  }
2123
2980
  // Add inline color overrides for better Grid3 compatibility
2124
2981
  if (button.style?.backgroundColor) {