PluginProbe
Tableberg – Simple Gutenberg Table Block / 1.2.0
Tableberg – Simple Gutenberg Table Block v1.2.0
1.2.0 1.1.5 1.1.4 1.1.3 1.1.2 1.1.1 1.1.0 1.0.5 1.0.4 1.0.3 1.0.2 1.0.1 trunk 0.0.2 0.2.1 0.3.2 0.3.3 0.4.1 0.5.0 0.5.1 0.5.2 0.5.3 0.5.4 0.5.5 0.5.6 All 43 releases
← All changes | renderer/Table/TableRenderer.php +98 -27 1.1.3 → 1.2.0 View file →
@@ -69,8 +69,19 @@
69 69 );
70 70 $stickyHeader = !empty($stickySettings['stickyHeader']);
71 71 $stickyFirstCol = !empty($stickySettings['stickyFirstCol']);
72 72
73 + // Row-only/column-only is Pro-owned. Free's empty default preserves
74 + // the attribute without enabling its editor or frontend behavior.
75 + $innerBorderType = apply_filters(
76 + 'tableberg/inner_border_type',
77 + '',
78 + $attrs->attrs
79 + );
80 + if (!in_array($innerBorderType, ['row', 'col'], true)) {
81 + $innerBorderType = '';
82 + }
83 +
73 84 $caption = $attrs->table->caption;
74 85 $tableWidth = trim($attrs->table->tableWidth->asAttr());
75 86 $tableAlignment = $attrs->table->tableAlignment->asAttr();
76 87 $cellSpacingHorizontal = trim($attrs->table->cellSpacing->horizontal->asAttr());
@@ -79,8 +90,24 @@
79 90 $tableBorderRight = trim($attrs->table->tableBorder->right->asAttr());
80 91 $tableBorderBottom = trim($attrs->table->tableBorder->bottom->asAttr());
81 92 $tableBorderLeft = trim($attrs->table->tableBorder->left->asAttr());
82 93 $fixedColumnWidths = $attrs->table->fixedColumnWidths->value();
94 + $tableRadius = [
95 + 'topLeft' => $attrs->cellDefaults->styles->borderRadius->topLeft->asAttr(),
96 + 'topRight' => $attrs->cellDefaults->styles->borderRadius->topRight->asAttr(),
97 + 'bottomRight' => $attrs->cellDefaults->styles->borderRadius->bottomRight->asAttr(),
98 + 'bottomLeft' => $attrs->cellDefaults->styles->borderRadius->bottomLeft->asAttr(),
99 + ];
100 + $isZeroRadius = function ($value) {
101 + $trimmed = trim((string) $value);
102 + return $trimmed === '' || preg_match('/^0(?:\.0+)?[a-z%]*$/i', $trimmed) === 1;
103 + };
104 + $hasRoundedCorners = count(array_filter(
105 + $tableRadius,
106 + function ($value) use ($isZeroRadius) {
107 + return !$isZeroRadius($value);
108 + }
109 + )) > 0;
83 110
84 111 $isHorizontalSpacingZero = $cellSpacingHorizontal === '0';
85 112 $isVerticalSpacingZero = $cellSpacingVertical === '0';
86 113 $hasCellSpacing = !$isHorizontalSpacingZero || !$isVerticalSpacingZero;
@@ -104,11 +131,19 @@
104 131 $canApplyCustomWidth,
105 132 $tableAlignment
106 133 );
107 134
108 - $tableStyles = [
109 - 'border-collapse: ' . ($hasCellSpacing ? 'separate' : 'collapse'),
110 - ];
135 + $tableStyles = array_merge(
136 + // Table-wide typography, inherited by everything in the cells that
137 + // does not set its own.
138 + $attrs->table->typography->asStyles(),
139 + [
140 + 'border-collapse: ' . ($hasCellSpacing ? 'separate' : 'collapse'),
141 + // Neutralize theme-level table borders. Tableberg owns its
142 + // borders through the table/cell controls and rounded wrapper.
143 + 'border: 0',
144 + ]
145 + );
111 146
112 147 if ($hasCellSpacing) {
113 148 $tableStyles[] = "border-spacing: {$cellSpacingHorizontal} {$cellSpacingVertical}";
114 149 }
@@ -119,21 +154,21 @@
119 154 } else {
120 155 $tableStyles[] = 'width: 100%';
121 156 }
122 157
123 - if ($tableBorderTop !== '') {
158 + if (!$hasRoundedCorners && $tableBorderTop !== '') {
124 159 $tableStyles[] = "border-top: {$tableBorderTop}";
125 160 }
126 161
127 - if ($tableBorderRight !== '') {
162 + if (!$hasRoundedCorners && $tableBorderRight !== '') {
128 163 $tableStyles[] = "border-right: {$tableBorderRight}";
129 164 }
130 165
131 - if ($tableBorderBottom !== '') {
166 + if (!$hasRoundedCorners && $tableBorderBottom !== '') {
132 167 $tableStyles[] = "border-bottom: {$tableBorderBottom}";
133 168 }
134 169
135 - if ($tableBorderLeft !== '') {
170 + if (!$hasRoundedCorners && $tableBorderLeft !== '') {
136 171 $tableStyles[] = "border-left: {$tableBorderLeft}";
137 172 }
138 173
139 174 $tableStyleAttr = "style='" . implode('; ', $tableStyles) . ";'";
@@ -244,13 +279,18 @@
244 279 'bottomLeft' => $attrs->cellDefaults->styles->borderRadius->bottomLeft->asAttr(),
245 280 ],
246 281 ];
247 282
248 - // The table border radius rounds the whole table's outer corners.
249 - // border-radius on collapsed-border tables/cells is ignored by
250 - // browsers, so it is rendered on the wrapper (with overflow:hidden)
251 - // and removed from the individual cells here.
252 - $tableRadius = $globalCellStyles['borderRadius'];
283 + // A collapsed table cannot reliably round its own explicit border.
284 + // The wrapper owns only the table border and clips the cell grid to
285 + // it. Cell borders stay on cells; copying them to the wrapper would
286 + // add an outline that the user did not configure as a table border.
287 + $tableOuterBorder = [
288 + 'top' => $tableBorderTop,
289 + 'right' => $tableBorderRight,
290 + 'bottom' => $tableBorderBottom,
291 + 'left' => $tableBorderLeft,
292 + ];
253 293 $globalCellStyles['borderRadius'] = [
254 294 'topLeft' => '',
255 295 'topRight' => '',
256 296 'bottomRight' => '',
@@ -368,9 +408,12 @@
368 408 $stickyHeader,
369 409 $stickyFirstCol,
370 410 $this->getCellClassName($cell),
371 411 $cell instanceof CellData ? $cell->attrs : [],
372 - $this->isCellEmpty($cell)
412 + $this->isCellEmpty($cell),
413 + $innerBorderType,
414 + $rows,
415 + $cols
373 416 )
374 417 );
375 418 }
376 419
@@ -378,8 +421,17 @@
378 421 if ($rowBackgroundColor !== '') {
379 422 $rowStyleParts[] = 'background-color:' . esc_attr($rowBackgroundColor);
380 423 }
381 424
425 + // Inherited by everything in the row's cells that has no colour
426 + // of its own.
427 + $rowTextColor = isset($rowStyles['textColor']) && is_string($rowStyles['textColor'])
428 + ? $rowStyles['textColor']
429 + : '';
430 + if ($rowTextColor !== '') {
431 + $rowStyleParts[] = 'color:' . esc_attr($rowTextColor);
432 + }
433 +
382 434 $rowBorder = isset($rowStyles['border']) && is_array($rowStyles['border'])
383 435 ? $rowStyles['border']
384 436 : [];
385 437 foreach (['top', 'right', 'bottom', 'left'] as $side) {
@@ -408,27 +460,29 @@
408 460 'sortable' => $sortType,
409 461 ];
410 462 }
411 463
412 - $columnsJson = json_encode($columnsData);
464 + $columnsJson = wp_json_encode($columnsData);
413 465 if (!is_string($columnsJson)) {
414 466 $columnsJson = '{}';
415 467 }
468 + $columnsJson = esc_attr($columnsJson);
416 469
417 - $paginationJson = json_encode($paginationConfig);
470 + $paginationJson = wp_json_encode($paginationConfig);
418 471 if (!is_string($paginationJson)) {
419 472 $paginationJson = '{}';
420 473 }
474 + $paginationJson = esc_attr($paginationJson);
421 475
476 + $searchPlaceholderAttr = esc_attr($searchPlaceholder);
477 + $searchPositionAttr = esc_attr($searchPosition);
478 + $searchHighlightColorAttr = esc_attr($searchHighlightColor);
479 +
422 480 $wrapperClass = trim("tableberg-table-wrapper {$wrapperAlignmentClass}");
423 481
424 - // Round the whole table's outer corners by clipping the wrapper.
482 + // Round the whole table's outer corners on the wrapper.
425 483 // Zero radii are skipped so a table without any actual rounding does
426 484 // not carry pointless border-radius declarations.
427 - $isZeroRadius = function ($value) {
428 - $trimmed = trim((string) $value);
429 - return $trimmed === '' || preg_match('/^0(?:\.0+)?[a-z%]*$/i', $trimmed) === 1;
430 - };
431 485 $wrapperStyles = [];
432 486 if (!$isZeroRadius($tableRadius['topLeft'])) {
433 487 $wrapperStyles[] = 'border-top-left-radius:' . $tableRadius['topLeft'];
434 488 }
@@ -441,8 +495,24 @@
441 495 if (!$isZeroRadius($tableRadius['bottomLeft'])) {
442 496 $wrapperStyles[] = 'border-bottom-left-radius:' . $tableRadius['bottomLeft'];
443 497 }
444 498
499 + if (!empty($wrapperStyles)) {
500 + if ($tableOuterBorder['top'] !== '') {
501 + $wrapperStyles[] = 'border-top:' . $tableOuterBorder['top'];
502 + }
503 + if ($tableOuterBorder['right'] !== '') {
504 + $wrapperStyles[] = 'border-right:' . $tableOuterBorder['right'];
505 + }
506 + if ($tableOuterBorder['bottom'] !== '') {
507 + $wrapperStyles[] = 'border-bottom:' . $tableOuterBorder['bottom'];
508 + }
509 + if ($tableOuterBorder['left'] !== '') {
510 + $wrapperStyles[] = 'border-left:' . $tableOuterBorder['left'];
511 + }
512 + $wrapperStyles[] = 'box-sizing:border-box';
513 + }
514 +
445 515 // A table wider than its wrapper must scroll inside the wrapper
446 516 // instead of pushing the whole page sideways, so the wrapper is a
447 517 // scroll container by default.
448 518 //
@@ -454,10 +524,8 @@
454 524 // scrolling wins and the header sticks within the wrapper.
455 525 //
456 526 // A rounded wrapper always needs the clip, so it opts in regardless.
457 527 $pageStickyHeader = $stickyHeader && !$stickyFirstCol;
458 - $hasRoundedCorners = !empty($wrapperStyles);
459 -
460 528 if ($hasRoundedCorners || !$pageStickyHeader) {
461 529 // `auto`, not `hidden`: both clip to the rounded corners, but
462 530 // `hidden` would also swallow a table wider than the wrapper.
463 531 // Inline, so it also wins over the `.tableberg-scroll-x` rule.
@@ -517,11 +585,11 @@
517 585 data-tableberg-sortable='$sortingBoolAsStr'
518 586 data-tableberg-columns='$columnsJson'
519 587 data-tableberg-pagination='$paginationJson'
520 588 data-tableberg-search-enabled='$searchEnabledAsStr'
521 - data-tableberg-search-placeholder='$searchPlaceholder'
522 - data-tableberg-search-position='$searchPosition'
523 - data-tableberg-search-highlight-color='$searchHighlightColor'
589 + data-tableberg-search-placeholder='$searchPlaceholderAttr'
590 + data-tableberg-search-position='$searchPositionAttr'
591 + data-tableberg-search-highlight-color='$searchHighlightColorAttr'
524 592 data-tableberg-header='$headerBoolAsStr'
525 593 data-tableberg-footer='$footerBoolAsStr'
526 594 {$responsiveDataAttrs}
527 595 >
@@ -593,8 +661,11 @@
593 661 $mobileMaxWidth = max(1, (int) $mobile->maxWidth->value());
594 662 $tabletStackCount = max(1, (int) $tablet->stackCount->value());
595 663 $mobileStackCount = max(1, (int) $mobile->stackCount->value());
596 664
665 + $tabletRepeatFirstCol = $tablet->repeatFirstCol->asAttr();
666 + $mobileRepeatFirstCol = $mobile->repeatFirstCol->asAttr();
667 +
597 668 return "
598 669 data-tableberg-responsive='true'
599 670 data-tableberg-rows='{$rows}'
600 671 data-tableberg-cols='{$cols}'
@@ -602,15 +673,15 @@
602 673 data-tableberg-tablet-width='{$tabletMaxWidth}'
603 674 data-tableberg-tablet-mode='{$tablet->mode->asAttr()}'
604 675 data-tableberg-tablet-transpose='{$tablet->transpose->asAttr()}'
605 676 data-tableberg-tablet-count='{$tabletStackCount}'
606 - data-tableberg-tablet-repeat-first-col='{$tablet->repeatFirstCol->asAttr()}'
677 + data-tableberg-tablet-repeat-first-col='{$tabletRepeatFirstCol}'
607 678 data-tableberg-mobile-enabled='{$mobile->enabled->asAttr()}'
608 679 data-tableberg-mobile-width='{$mobileMaxWidth}'
609 680 data-tableberg-mobile-mode='{$mobile->mode->asAttr()}'
610 681 data-tableberg-mobile-transpose='{$mobile->transpose->asAttr()}'
611 682 data-tableberg-mobile-count='{$mobileStackCount}'
612 - data-tableberg-mobile-repeat-first-col='{$mobile->repeatFirstCol->asAttr()}'
683 + data-tableberg-mobile-repeat-first-col='{$mobileRepeatFirstCol}'
613 684 ";
614 685 }
615 686
616 687 private function getCell($row, $col, $cells) {