opentiny 6.9.21 → 6.9.23

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opentiny",
3
- "version": "6.9.21",
3
+ "version": "6.9.23",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/mild-blue/opentiny"
@@ -948,9 +948,9 @@
948
948
  var global$1 = tinymce.util.Tools.resolve('tinymce.Env');
949
949
 
950
950
  const defaultTableToolbar = 'tableprops tabledelete | tableinsertrowbefore tableinsertrowafter tabledeleterow | tableinsertcolbefore tableinsertcolafter tabledeletecol';
951
- const defaultTableCellInputs = 'width celltype scope halign valign class';
952
- const defaultTableRowInputs = 'type align height class';
953
- const defaultTableInputs = 'width height cellspacing cellpadding border caption align class';
951
+ const defaultTableCellInputs = 'width height celltype scope halign valign backgroundcolor class';
952
+ const defaultTableRowInputs = 'type align backgroundcolor class';
953
+ const defaultTableInputs = 'width height cellspacing cellpadding border backgroundcolor caption align class';
954
954
  const defaultCellBorderWidths = range(5, i => {
955
955
  const size = `${ i + 1 }px`;
956
956
  return {
@@ -1067,6 +1067,26 @@
1067
1067
  processor: 'string',
1068
1068
  default: defaultTableToolbar
1069
1069
  });
1070
+ registerOption('table_contextmenu', {
1071
+ processor: 'string[]',
1072
+ default: []
1073
+ });
1074
+ registerOption('table_contextmenu_flatten', {
1075
+ processor: 'boolean',
1076
+ default: false
1077
+ });
1078
+ registerOption('table_row_contextmenu', {
1079
+ processor: 'string[]',
1080
+ default: []
1081
+ });
1082
+ registerOption('table_column_contextmenu', {
1083
+ processor: 'string[]',
1084
+ default: []
1085
+ });
1086
+ registerOption('table_cell_contextmenu', {
1087
+ processor: 'string[]',
1088
+ default: []
1089
+ });
1070
1090
  registerOption('table_background_color_map', {
1071
1091
  processor: 'object[]',
1072
1092
  default: []
@@ -1091,6 +1111,11 @@
1091
1111
  const getRowClassList = option('table_row_class_list');
1092
1112
  const getTableClassList = option('table_class_list');
1093
1113
  const getToolbar = option('table_toolbar');
1114
+ const getTableContextMenu = option('table_contextmenu');
1115
+ const getTableContextMenuFlatten = option('table_contextmenu_flatten');
1116
+ const getTableRowContextMenu = option('table_row_contextmenu');
1117
+ const getTableColumnContextMenu = option('table_column_contextmenu');
1118
+ const getTableCellContextMenu = option('table_cell_contextmenu');
1094
1119
  const getTableBackgroundColorMap = option('table_background_color_map');
1095
1120
  const getTableBorderColorMap = option('table_border_color_map');
1096
1121
  const isPixelsForced = editor => getTableSizingMode(editor) === 'fixed';
@@ -1105,6 +1130,11 @@
1105
1130
  const defaultAttributes = options.get('table_default_attributes');
1106
1131
  return options.isSet('table_default_attributes') ? defaultAttributes : determineDefaultAttributes(editor, defaultAttributes);
1107
1132
  };
1133
+ const isTableContextMenuSet = editor => editor.options.isSet('table_contextmenu');
1134
+ const isTableContextMenuFlatten = editor => getTableContextMenuFlatten(editor);
1135
+ const isTableRowContextMenuSet = editor => editor.options.isSet('table_row_contextmenu');
1136
+ const isTableColumnContextMenuSet = editor => editor.options.isSet('table_column_contextmenu');
1137
+ const isTableCellContextMenuSet = editor => editor.options.isSet('table_cell_contextmenu');
1108
1138
 
1109
1139
  const isWithin = (bounds, detail) => {
1110
1140
  return detail.column >= bounds.startCol && detail.column + detail.colspan - 1 <= bounds.finishCol && detail.row >= bounds.startRow && detail.row + detail.rowspan - 1 <= bounds.finishRow;
@@ -1676,6 +1706,48 @@
1676
1706
  return isNotEmpty(item.value) ? [item] : [];
1677
1707
  }
1678
1708
  });
1709
+ const filterContextMenu = (menu, allowed) => {
1710
+ if (allowed.length === 0) {
1711
+ return '';
1712
+ }
1713
+ const allowedSet = new Set(allowed);
1714
+ const filteredGroups = menu.split('|').map(group => group.trim()).map(group => group.length === 0 ? [] : group.split(/\s+/).filter(item => allowedSet.has(item))).filter(items => items.length > 0).map(items => items.join(' '));
1715
+ return filteredGroups.join(' | ');
1716
+ };
1717
+ const flattenContextMenu = (menu, replacements) => {
1718
+ const groups = menu.split('|').map(group => group.trim()).filter(group => group.length > 0);
1719
+ const flattened = [];
1720
+ const addGroup = items => {
1721
+ if (items.length > 0) {
1722
+ flattened.push(items.join(' '));
1723
+ }
1724
+ };
1725
+ each(groups, group => {
1726
+ const tokens = group.split(/\s+/).filter(token => token.length > 0);
1727
+ let current = [];
1728
+ each(tokens, token => {
1729
+ const replacement = replacements[token];
1730
+ if (replacement === undefined) {
1731
+ current.push(token);
1732
+ } else if (replacement.length === 0) {
1733
+ return;
1734
+ } else {
1735
+ const replacementGroups = replacement.split('|').map(repGroup => repGroup.trim()).filter(repGroup => repGroup.length > 0);
1736
+ if (replacementGroups.length === 1) {
1737
+ current = current.concat(replacementGroups[0].split(/\s+/).filter(item => item.length > 0));
1738
+ } else {
1739
+ addGroup(current);
1740
+ current = [];
1741
+ each(replacementGroups, repGroup => {
1742
+ addGroup(repGroup.split(/\s+/).filter(item => item.length > 0));
1743
+ });
1744
+ }
1745
+ }
1746
+ });
1747
+ addGroup(current);
1748
+ });
1749
+ return flattened.join(' | ');
1750
+ };
1679
1751
  const generateMenuItemsCallback = (editor, items, format, onAction) => callback => callback(buildMenuItems(editor, items, format, onAction));
1680
1752
  const buildColorMenu = (editor, colorList, style) => {
1681
1753
  const colorMap = map(colorList, entry => ({
@@ -1720,6 +1792,18 @@
1720
1792
  label: 'Width',
1721
1793
  tooltip: 'Cell width in pixels or percentage (e.g., 50px or 10%).'
1722
1794
  },
1795
+ {
1796
+ name: 'height',
1797
+ type: 'input',
1798
+ label: 'Height',
1799
+ tooltip: 'Row height in pixels (e.g., 20px). If the height change does not apply to the row, remove the table height in Table Properties and try again.'
1800
+ },
1801
+ {
1802
+ name: 'backgroundcolor',
1803
+ type: 'colorinput',
1804
+ label: 'Background color',
1805
+ tooltip: 'Background color of the cell.'
1806
+ },
1723
1807
  {
1724
1808
  name: 'celltype',
1725
1809
  type: 'listbox',
@@ -1817,16 +1901,6 @@
1817
1901
  return `Color of the outer border of the ${ dialogName }.`;
1818
1902
  }
1819
1903
  };
1820
- const getBackgroundColourTooltip = dialogName => {
1821
- switch (dialogName) {
1822
- case 'table':
1823
- return 'Changes the background color of all cells in the table, except for those set individually through Cell Properties or Row Properties.';
1824
- case 'row':
1825
- return 'Changes the background color of all cells in the row, except for those set individually through Cell Properties.';
1826
- case 'cell':
1827
- return `Background color of the cell.`;
1828
- }
1829
- };
1830
1904
  const getBorderWidthTooltip = dialogName => {
1831
1905
  switch (dialogName) {
1832
1906
  case 'table':
@@ -1856,12 +1930,6 @@
1856
1930
  type: 'colorinput',
1857
1931
  label: 'Border color',
1858
1932
  tooltip: getBorderColorTooltip(dialogName)
1859
- },
1860
- {
1861
- name: 'backgroundcolor',
1862
- type: 'colorinput',
1863
- label: 'Background color',
1864
- tooltip: getBackgroundColourTooltip(dialogName)
1865
1933
  }
1866
1934
  ];
1867
1935
  const borderWidth = {
@@ -1872,7 +1940,7 @@
1872
1940
  };
1873
1941
  const items = dialogName === 'cell' ? [borderWidth].concat(advTabItems) : advTabItems;
1874
1942
  return {
1875
- title: 'Advanced',
1943
+ title: 'Border',
1876
1944
  name: 'advanced',
1877
1945
  items
1878
1946
  };
@@ -2199,7 +2267,6 @@
2199
2267
  const extractDataFromRowElement = (editor, elm, hasAdvancedRowTab) => {
2200
2268
  const dom = editor.dom;
2201
2269
  return {
2202
- height: dom.getStyle(elm, 'height') || dom.getAttrib(elm, 'height'),
2203
2270
  class: dom.getAttrib(elm, 'class', ''),
2204
2271
  type: getRowType(elm),
2205
2272
  align: getHAlignment(editor, elm),
@@ -2209,9 +2276,11 @@
2209
2276
  const extractDataFromCellElement = (editor, cell, hasAdvancedCellTab, column) => {
2210
2277
  const dom = editor.dom;
2211
2278
  const colElm = column.getOr(cell);
2279
+ const rowElm = cell.parentElement;
2212
2280
  const getStyle = (element, style) => dom.getStyle(element, style) || dom.getAttrib(element, style);
2213
2281
  return {
2214
2282
  width: getStyle(colElm, 'width'),
2283
+ height: rowElm ? dom.getStyle(rowElm, 'height') || dom.getAttrib(rowElm, 'height') : '',
2215
2284
  scope: dom.getAttrib(cell, 'scope'),
2216
2285
  celltype: getNodeName(cell),
2217
2286
  class: dom.getAttrib(cell, 'class', ''),
@@ -2265,6 +2334,7 @@
2265
2334
  };
2266
2335
  const applyStyleData$1 = (editor, cells, data, wasChanged) => {
2267
2336
  const isSingleCell = cells.length === 1;
2337
+ const rowsSeen = new Set();
2268
2338
  each(cells, item => {
2269
2339
  const cellElm = item.element;
2270
2340
  const shouldOverrideCurrentValue = isSingleCell ? always : wasChanged;
@@ -2274,6 +2344,16 @@
2274
2344
  if (hasAdvancedCellTab(editor)) {
2275
2345
  updateAdvancedProps$1(modifier, data, shouldOverrideCurrentValue);
2276
2346
  }
2347
+ if (shouldOverrideCurrentValue('height')) {
2348
+ const rowElm = cellElm.parentElement;
2349
+ if (rowElm !== null && !rowsSeen.has(rowElm)) {
2350
+ rowsSeen.add(rowElm);
2351
+ editor.dom.setStyle(rowElm, 'height', addPxSuffix(data.height));
2352
+ if (wasChanged('height')) {
2353
+ Array.from(rowElm.cells).forEach(cell => editor.dom.setStyle(cell, 'height', null));
2354
+ }
2355
+ }
2356
+ }
2277
2357
  if (wasChanged('halign')) {
2278
2358
  setAlign(editor, cellElm, data.halign);
2279
2359
  }
@@ -2419,10 +2499,10 @@
2419
2499
  ]
2420
2500
  },
2421
2501
  {
2422
- label: 'Height',
2423
- name: 'height',
2424
- type: 'input',
2425
- tooltip: 'Row height in pixels (e.g., 20px).'
2502
+ name: 'backgroundcolor',
2503
+ type: 'colorinput',
2504
+ label: 'Background color',
2505
+ tooltip: 'Changes the background color of all cells in the row, except for those set individually through Cell Properties.'
2426
2506
  }
2427
2507
  ];
2428
2508
  const getItems$1 = editor => {
@@ -2440,9 +2520,6 @@
2440
2520
  if (shouldUpdate('class') && data.class !== 'mce-no-match') {
2441
2521
  modifier.setAttrib('class', data.class);
2442
2522
  }
2443
- if (shouldUpdate('height')) {
2444
- modifier.setStyle('height', addPxSuffix(data.height));
2445
- }
2446
2523
  };
2447
2524
  const updateAdvancedProps = (modifier, data, shouldUpdate) => {
2448
2525
  if (shouldUpdate('backgroundcolor')) {
@@ -2459,17 +2536,11 @@
2459
2536
  const isSingleRow = rows.length === 1;
2460
2537
  const shouldOverrideCurrentValue = isSingleRow ? always : wasChanged;
2461
2538
  each(rows, rowElm => {
2462
- const rowCells = children$1(SugarElement.fromDom(rowElm), 'td,th');
2463
2539
  const modifier = DomModifier.normal(editor, rowElm);
2464
2540
  updateSimpleProps(modifier, data, shouldOverrideCurrentValue);
2465
2541
  if (hasAdvancedRowTab(editor)) {
2466
2542
  updateAdvancedProps(modifier, data, shouldOverrideCurrentValue);
2467
2543
  }
2468
- if (wasChanged('height')) {
2469
- each(rowCells, cell => {
2470
- editor.dom.setStyle(cell.dom, 'height', null);
2471
- });
2472
- }
2473
2544
  if (wasChanged('align')) {
2474
2545
  setAlign(editor, rowElm, data.align);
2475
2546
  }
@@ -2602,6 +2673,12 @@
2602
2673
  label: 'Border width',
2603
2674
  tooltip: 'Width of the border for the entire table and individual cells.'
2604
2675
  },
2676
+ {
2677
+ name: 'backgroundcolor',
2678
+ type: 'colorinput',
2679
+ label: 'Background color',
2680
+ tooltip: 'Changes the background color of all cells in the table, except for those set individually through Cell Properties or Row Properties.'
2681
+ },
2605
2682
  {
2606
2683
  type: 'label',
2607
2684
  label: 'Caption',
@@ -3023,12 +3100,40 @@
3023
3100
  editor.off('NodeChange', nodeChanged);
3024
3101
  };
3025
3102
  };
3103
+ const getFilteredRowMenuItems = editor => {
3104
+ const rowMenuItems = 'tableinsertrowbefore tableinsertrowafter tabledeleterow tablerowprops | tablecutrow tablecopyrow tablepasterowbefore tablepasterowafter';
3105
+ return isTableRowContextMenuSet(editor) ? filterContextMenu(rowMenuItems, getTableRowContextMenu(editor)) : rowMenuItems;
3106
+ };
3107
+ const getFilteredColumnMenuItems = editor => {
3108
+ const columnMenuItems = 'tableinsertcolumnbefore tableinsertcolumnafter tabledeletecolumn | tablecutcolumn tablecopycolumn tablepastecolumnbefore tablepastecolumnafter';
3109
+ return isTableColumnContextMenuSet(editor) ? filterContextMenu(columnMenuItems, getTableColumnContextMenu(editor)) : columnMenuItems;
3110
+ };
3111
+ const getFilteredCellMenuItems = editor => {
3112
+ const cellMenuItems = 'tablecellprops tablemergecells tablesplitcells';
3113
+ return isTableCellContextMenuSet(editor) ? filterContextMenu(cellMenuItems, getTableCellContextMenu(editor)) : cellMenuItems;
3114
+ };
3115
+ const getTableMenuItems = editor => {
3116
+ const menu = 'inserttable | cell row column | advtablesort | tableprops deletetable';
3117
+ const filteredMenu = isTableContextMenuSet(editor) ? filterContextMenu(menu, [
3118
+ 'inserttable',
3119
+ ...getTableContextMenu(editor)
3120
+ ]) : menu;
3121
+ if (isTableContextMenuFlatten(editor) && filteredMenu.length > 0) {
3122
+ return flattenContextMenu(filteredMenu, {
3123
+ cell: getFilteredCellMenuItems(editor),
3124
+ row: getFilteredRowMenuItems(editor),
3125
+ column: getFilteredColumnMenuItems(editor)
3126
+ });
3127
+ } else {
3128
+ return filteredMenu;
3129
+ }
3130
+ };
3026
3131
  const addButtons = (editor, selectionTargets) => {
3027
3132
  editor.ui.registry.addMenuButton('table', {
3028
3133
  tooltip: 'Table',
3029
3134
  icon: 'table',
3030
3135
  onSetup: onSetupEditable$1(editor),
3031
- fetch: callback => callback('inserttable | cell row column | advtablesort | tableprops deletetable')
3136
+ fetch: callback => callback(getTableMenuItems(editor))
3032
3137
  });
3033
3138
  const cmd = command => () => editor.execCommand(command);
3034
3139
  const addButtonIfRegistered = (name, spec) => {
@@ -3444,37 +3549,53 @@
3444
3549
  onSetup: selectionTargets.onSetupTable,
3445
3550
  command: 'mceTableDelete'
3446
3551
  });
3447
- if (contains(hasRowMenuItems, true)) {
3552
+ const rowMenuItems = 'tableinsertrowbefore tableinsertrowafter tabledeleterow tablerowprops | tablecutrow tablecopyrow tablepasterowbefore tablepasterowafter';
3553
+ const filteredRowMenuItems = isTableRowContextMenuSet(editor) ? filterContextMenu(rowMenuItems, getTableRowContextMenu(editor)) : rowMenuItems;
3554
+ if (contains(hasRowMenuItems, true) && filteredRowMenuItems.length > 0) {
3448
3555
  editor.ui.registry.addNestedMenuItem('row', {
3449
3556
  type: 'nestedmenuitem',
3450
3557
  text: 'Row',
3451
- getSubmenuItems: constant('tableinsertrowbefore tableinsertrowafter tabledeleterow tablerowprops | tablecutrow tablecopyrow tablepasterowbefore tablepasterowafter')
3558
+ getSubmenuItems: constant(filteredRowMenuItems)
3452
3559
  });
3453
3560
  }
3454
- if (contains(hasColumnMenuItems, true)) {
3561
+ const columnMenuItems = 'tableinsertcolumnbefore tableinsertcolumnafter tabledeletecolumn | tablecutcolumn tablecopycolumn tablepastecolumnbefore tablepastecolumnafter';
3562
+ const filteredColumnMenuItems = isTableColumnContextMenuSet(editor) ? filterContextMenu(columnMenuItems, getTableColumnContextMenu(editor)) : columnMenuItems;
3563
+ if (contains(hasColumnMenuItems, true) && filteredColumnMenuItems.length > 0) {
3455
3564
  editor.ui.registry.addNestedMenuItem('column', {
3456
3565
  type: 'nestedmenuitem',
3457
3566
  text: 'Column',
3458
- getSubmenuItems: constant('tableinsertcolumnbefore tableinsertcolumnafter tabledeletecolumn | tablecutcolumn tablecopycolumn tablepastecolumnbefore tablepastecolumnafter')
3567
+ getSubmenuItems: constant(filteredColumnMenuItems)
3459
3568
  });
3460
3569
  }
3461
- if (contains(hasCellMenuItems, true)) {
3570
+ const cellMenuItems = 'tablecellprops tablemergecells tablesplitcells';
3571
+ const filteredCellMenuItems = isTableCellContextMenuSet(editor) ? filterContextMenu(cellMenuItems, getTableCellContextMenu(editor)) : cellMenuItems;
3572
+ if (contains(hasCellMenuItems, true) && filteredCellMenuItems.length > 0) {
3462
3573
  editor.ui.registry.addNestedMenuItem('cell', {
3463
3574
  type: 'nestedmenuitem',
3464
3575
  text: 'Cell',
3465
- getSubmenuItems: constant('tablecellprops tablemergecells tablesplitcells')
3576
+ getSubmenuItems: constant(filteredCellMenuItems)
3466
3577
  });
3467
3578
  }
3468
3579
  editor.ui.registry.addContextMenu('table', {
3469
3580
  update: () => {
3470
3581
  selectionTargets.resetTargets();
3471
- return selectionTargets.targets().fold(constant(''), targets => {
3582
+ const menu = selectionTargets.targets().fold(constant(''), targets => {
3472
3583
  if (name(targets.element) === 'caption') {
3473
3584
  return 'tableprops deletetable';
3474
3585
  } else {
3475
3586
  return 'cell row column | advtablesort | tableprops deletetable';
3476
3587
  }
3477
3588
  });
3589
+ const filteredMenu = isTableContextMenuSet(editor) ? filterContextMenu(menu, getTableContextMenu(editor)) : menu;
3590
+ if (isTableContextMenuFlatten(editor) && filteredMenu.length > 0) {
3591
+ return flattenContextMenu(filteredMenu, {
3592
+ cell: filteredCellMenuItems,
3593
+ row: filteredRowMenuItems,
3594
+ column: filteredColumnMenuItems
3595
+ });
3596
+ } else {
3597
+ return filteredMenu;
3598
+ }
3478
3599
  }
3479
3600
  });
3480
3601
  const tableClassList = filterNoneItem(getTableClassList(editor));