@wordpress/block-library 9.20.0 → 9.22.0

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 (199) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/build/categories/edit.js +3 -3
  3. package/build/categories/edit.js.map +1 -1
  4. package/build/cover/index.js +1 -1
  5. package/build/cover/index.js.map +1 -1
  6. package/build/details/edit.js +1 -5
  7. package/build/details/edit.js.map +1 -1
  8. package/build/details/index.js +1 -1
  9. package/build/details/index.js.map +1 -1
  10. package/build/embed/edit.js +4 -1
  11. package/build/embed/edit.js.map +1 -1
  12. package/build/image/edit.js +3 -2
  13. package/build/image/edit.js.map +1 -1
  14. package/build/image/image.js +13 -8
  15. package/build/image/image.js.map +1 -1
  16. package/build/navigation/edit/index.js +8 -4
  17. package/build/navigation/edit/index.js.map +1 -1
  18. package/build/navigation/view.js +2 -1
  19. package/build/navigation/view.js.map +1 -1
  20. package/build/navigation-link/edit.js +27 -29
  21. package/build/navigation-link/edit.js.map +1 -1
  22. package/build/navigation-link/index.js +0 -3
  23. package/build/navigation-link/index.js.map +1 -1
  24. package/build/navigation-link/transforms.js +0 -2
  25. package/build/navigation-link/transforms.js.map +1 -1
  26. package/build/navigation-link/update-attributes.js +0 -1
  27. package/build/navigation-link/update-attributes.js.map +1 -1
  28. package/build/navigation-submenu/edit.js +1 -24
  29. package/build/navigation-submenu/edit.js.map +1 -1
  30. package/build/navigation-submenu/index.js +0 -3
  31. package/build/navigation-submenu/index.js.map +1 -1
  32. package/build/post-comments-count/index.js +0 -1
  33. package/build/post-comments-count/index.js.map +1 -1
  34. package/build/post-comments-link/index.js +0 -1
  35. package/build/post-comments-link/index.js.map +1 -1
  36. package/build/post-featured-image/edit.js +14 -3
  37. package/build/post-featured-image/edit.js.map +1 -1
  38. package/build/query/edit/inspector-controls/index.js +47 -59
  39. package/build/query/edit/inspector-controls/index.js.map +1 -1
  40. package/build/query/edit/inspector-controls/parent-control.js +2 -2
  41. package/build/query/edit/inspector-controls/parent-control.js.map +1 -1
  42. package/build/query/edit/inspector-controls/taxonomy-controls.js +2 -2
  43. package/build/query/edit/inspector-controls/taxonomy-controls.js.map +1 -1
  44. package/build/query/edit/query-content.js +4 -17
  45. package/build/query/edit/query-content.js.map +1 -1
  46. package/build/query-total/index.js +3 -0
  47. package/build/query-total/index.js.map +1 -1
  48. package/build/quote/index.js +1 -1
  49. package/build/quote/index.js.map +1 -1
  50. package/build/rss/edit.js +21 -1
  51. package/build/rss/edit.js.map +1 -1
  52. package/build/rss/index.js +7 -0
  53. package/build/rss/index.js.map +1 -1
  54. package/build/site-title/edit.js +1 -1
  55. package/build/site-title/edit.js.map +1 -1
  56. package/build/social-links/edit.js +29 -31
  57. package/build/social-links/edit.js.map +1 -1
  58. package/build/table/index.js +3 -3
  59. package/build/table/index.js.map +1 -1
  60. package/build/table/transforms.js +11 -3
  61. package/build/table/transforms.js.map +1 -1
  62. package/build/table-of-contents/edit.js +50 -8
  63. package/build/table-of-contents/edit.js.map +1 -1
  64. package/build/table-of-contents/hooks.js +13 -4
  65. package/build/table-of-contents/hooks.js.map +1 -1
  66. package/build/table-of-contents/index.js +3 -0
  67. package/build/table-of-contents/index.js.map +1 -1
  68. package/build-module/categories/edit.js +3 -3
  69. package/build-module/categories/edit.js.map +1 -1
  70. package/build-module/cover/index.js +1 -1
  71. package/build-module/cover/index.js.map +1 -1
  72. package/build-module/details/edit.js +1 -5
  73. package/build-module/details/edit.js.map +1 -1
  74. package/build-module/details/index.js +1 -1
  75. package/build-module/details/index.js.map +1 -1
  76. package/build-module/embed/edit.js +4 -1
  77. package/build-module/embed/edit.js.map +1 -1
  78. package/build-module/image/edit.js +3 -2
  79. package/build-module/image/edit.js.map +1 -1
  80. package/build-module/image/image.js +14 -9
  81. package/build-module/image/image.js.map +1 -1
  82. package/build-module/navigation/edit/index.js +8 -4
  83. package/build-module/navigation/edit/index.js.map +1 -1
  84. package/build-module/navigation/view.js +2 -1
  85. package/build-module/navigation/view.js.map +1 -1
  86. package/build-module/navigation-link/edit.js +28 -30
  87. package/build-module/navigation-link/edit.js.map +1 -1
  88. package/build-module/navigation-link/index.js +0 -3
  89. package/build-module/navigation-link/index.js.map +1 -1
  90. package/build-module/navigation-link/transforms.js +0 -2
  91. package/build-module/navigation-link/transforms.js.map +1 -1
  92. package/build-module/navigation-link/update-attributes.js +0 -1
  93. package/build-module/navigation-link/update-attributes.js.map +1 -1
  94. package/build-module/navigation-submenu/edit.js +1 -24
  95. package/build-module/navigation-submenu/edit.js.map +1 -1
  96. package/build-module/navigation-submenu/index.js +0 -3
  97. package/build-module/navigation-submenu/index.js.map +1 -1
  98. package/build-module/post-comments-count/index.js +0 -1
  99. package/build-module/post-comments-count/index.js.map +1 -1
  100. package/build-module/post-comments-link/index.js +0 -1
  101. package/build-module/post-comments-link/index.js.map +1 -1
  102. package/build-module/post-featured-image/edit.js +14 -3
  103. package/build-module/post-featured-image/edit.js.map +1 -1
  104. package/build-module/query/edit/inspector-controls/index.js +49 -61
  105. package/build-module/query/edit/inspector-controls/index.js.map +1 -1
  106. package/build-module/query/edit/inspector-controls/parent-control.js +2 -2
  107. package/build-module/query/edit/inspector-controls/parent-control.js.map +1 -1
  108. package/build-module/query/edit/inspector-controls/taxonomy-controls.js +2 -2
  109. package/build-module/query/edit/inspector-controls/taxonomy-controls.js.map +1 -1
  110. package/build-module/query/edit/query-content.js +4 -17
  111. package/build-module/query/edit/query-content.js.map +1 -1
  112. package/build-module/query-total/index.js +3 -0
  113. package/build-module/query-total/index.js.map +1 -1
  114. package/build-module/quote/index.js +1 -1
  115. package/build-module/quote/index.js.map +1 -1
  116. package/build-module/rss/edit.js +22 -2
  117. package/build-module/rss/edit.js.map +1 -1
  118. package/build-module/rss/index.js +7 -0
  119. package/build-module/rss/index.js.map +1 -1
  120. package/build-module/site-title/edit.js +1 -1
  121. package/build-module/site-title/edit.js.map +1 -1
  122. package/build-module/social-links/edit.js +30 -32
  123. package/build-module/social-links/edit.js.map +1 -1
  124. package/build-module/table/index.js +3 -3
  125. package/build-module/table/index.js.map +1 -1
  126. package/build-module/table/transforms.js +11 -3
  127. package/build-module/table/transforms.js.map +1 -1
  128. package/build-module/table-of-contents/edit.js +52 -10
  129. package/build-module/table-of-contents/edit.js.map +1 -1
  130. package/build-module/table-of-contents/hooks.js +13 -4
  131. package/build-module/table-of-contents/hooks.js.map +1 -1
  132. package/build-module/table-of-contents/index.js +3 -0
  133. package/build-module/table-of-contents/index.js.map +1 -1
  134. package/build-style/editor-rtl.css +1 -50
  135. package/build-style/editor.css +1 -50
  136. package/build-style/media-text/style-rtl.css +0 -2
  137. package/build-style/media-text/style.css +0 -2
  138. package/build-style/post-comments-form/style-rtl.css +3 -0
  139. package/build-style/post-comments-form/style.css +3 -0
  140. package/build-style/search/style-rtl.css +1 -0
  141. package/build-style/search/style.css +1 -0
  142. package/build-style/social-links/editor-rtl.css +1 -50
  143. package/build-style/social-links/editor.css +1 -50
  144. package/build-style/style-rtl.css +4 -6
  145. package/build-style/style.css +4 -6
  146. package/build-style/tag-cloud/style-rtl.css +0 -4
  147. package/build-style/tag-cloud/style.css +0 -4
  148. package/package.json +35 -35
  149. package/src/button/index.php +2 -3
  150. package/src/categories/edit.js +3 -3
  151. package/src/cover/index.js +1 -1
  152. package/src/details/edit.js +6 -8
  153. package/src/details/index.js +1 -1
  154. package/src/embed/edit.js +7 -1
  155. package/src/file/index.php +2 -3
  156. package/src/image/edit.js +3 -3
  157. package/src/image/image.js +9 -12
  158. package/src/latest-comments/index.php +1 -1
  159. package/src/latest-posts/index.php +3 -0
  160. package/src/media-text/style.scss +0 -2
  161. package/src/navigation/edit/index.js +4 -0
  162. package/src/navigation/index.php +1 -1
  163. package/src/navigation/view.js +2 -1
  164. package/src/navigation-link/block.json +0 -3
  165. package/src/navigation-link/edit.js +46 -33
  166. package/src/navigation-link/index.php +1 -5
  167. package/src/navigation-link/transforms.js +1 -2
  168. package/src/navigation-link/update-attributes.js +0 -1
  169. package/src/navigation-submenu/block.json +0 -3
  170. package/src/navigation-submenu/edit.js +1 -24
  171. package/src/navigation-submenu/index.php +0 -4
  172. package/src/post-comments-count/block.json +0 -1
  173. package/src/post-comments-count/index.php +4 -0
  174. package/src/post-comments-form/style.scss +5 -0
  175. package/src/post-comments-link/block.json +0 -1
  176. package/src/post-comments-link/index.php +4 -0
  177. package/src/post-featured-image/edit.js +93 -75
  178. package/src/query/edit/inspector-controls/index.js +66 -91
  179. package/src/query/edit/inspector-controls/parent-control.js +2 -2
  180. package/src/query/edit/inspector-controls/taxonomy-controls.js +2 -2
  181. package/src/query/edit/query-content.js +7 -16
  182. package/src/query-total/block.json +3 -0
  183. package/src/query-total/index.php +1 -1
  184. package/src/quote/index.js +1 -1
  185. package/src/rss/block.json +7 -0
  186. package/src/rss/edit.js +21 -0
  187. package/src/rss/index.php +27 -9
  188. package/src/search/index.php +12 -9
  189. package/src/search/style.scss +1 -0
  190. package/src/site-title/edit.js +1 -1
  191. package/src/site-title/index.php +1 -1
  192. package/src/social-links/edit.js +29 -30
  193. package/src/social-links/editor.scss +1 -59
  194. package/src/table/index.js +3 -3
  195. package/src/table/transforms.js +14 -2
  196. package/src/table-of-contents/block.json +3 -0
  197. package/src/table-of-contents/edit.js +45 -4
  198. package/src/table-of-contents/hooks.js +12 -3
  199. package/src/tag-cloud/style.scss +0 -5
package/src/rss/index.php CHANGED
@@ -31,6 +31,20 @@ function render_block_core_rss( $attributes ) {
31
31
 
32
32
  $rss_items = $rss->get_items( 0, $attributes['itemsToShow'] );
33
33
  $list_items = '';
34
+
35
+ $open_in_new_tab = ! empty( $attributes['openInNewTab'] );
36
+ $rel = ! empty( $attributes['rel'] ) ? trim( $attributes['rel'] ) : '';
37
+
38
+ $link_attributes = '';
39
+
40
+ if ( $open_in_new_tab ) {
41
+ $link_attributes .= ' target="_blank"';
42
+ }
43
+
44
+ if ( '' !== $rel ) {
45
+ $link_attributes .= ' rel="' . esc_attr( $rel ) . '"';
46
+ }
47
+
34
48
  foreach ( $rss_items as $item ) {
35
49
  $title = esc_html( trim( strip_tags( $item->get_title() ) ) );
36
50
  if ( empty( $title ) ) {
@@ -38,20 +52,24 @@ function render_block_core_rss( $attributes ) {
38
52
  }
39
53
  $link = $item->get_link();
40
54
  $link = esc_url( $link );
55
+
41
56
  if ( $link ) {
42
- $title = "<a href='{$link}'>{$title}</a>";
57
+ $title = "<a href='{$link}'{$link_attributes}>{$title}</a>";
43
58
  }
44
59
  $title = "<div class='wp-block-rss__item-title'>{$title}</div>";
45
60
 
46
- $date = '';
47
- if ( $attributes['displayDate'] ) {
48
- $date = $item->get_date( 'U' );
61
+ $date_markup = '';
62
+ if ( ! empty( $attributes['displayDate'] ) ) {
63
+ $timestamp = $item->get_date( 'U' );
64
+
65
+ if ( $timestamp ) {
66
+ $gmt_offset = get_option( 'gmt_offset' );
67
+ $timestamp += (int) ( (float) $gmt_offset * HOUR_IN_SECONDS );
49
68
 
50
- if ( $date ) {
51
- $date = sprintf(
69
+ $date_markup = sprintf(
52
70
  '<time datetime="%1$s" class="wp-block-rss__item-publish-date">%2$s</time> ',
53
- esc_attr( date_i18n( 'c', $date ) ),
54
- esc_attr( date_i18n( get_option( 'date_format' ), $date ) )
71
+ esc_attr( date_i18n( 'c', $timestamp ) ),
72
+ esc_html( date_i18n( get_option( 'date_format' ), $timestamp ) )
55
73
  );
56
74
  }
57
75
  }
@@ -85,7 +103,7 @@ function render_block_core_rss( $attributes ) {
85
103
  $excerpt = '<div class="wp-block-rss__item-excerpt">' . esc_html( $excerpt ) . '</div>';
86
104
  }
87
105
 
88
- $list_items .= "<li class='wp-block-rss__item'>{$title}{$date}{$author}{$excerpt}</li>";
106
+ $list_items .= "<li class='wp-block-rss__item'>{$title}{$date_markup}{$author}{$excerpt}</li>";
89
107
  }
90
108
 
91
109
  $classnames = array();
@@ -10,9 +10,7 @@
10
10
  *
11
11
  * @since 6.3.0 Using block.json `viewScript` to register script, and update `view_script_handles()` only when needed.
12
12
  *
13
- * @param array $attributes The block attributes.
14
- * @param string $content The saved content.
15
- * @param WP_Block $block The parsed block.
13
+ * @param array $attributes The block attributes.
16
14
  *
17
15
  * @return string The search block markup.
18
16
  */
@@ -152,17 +150,22 @@ function render_block_core_search( $attributes ) {
152
150
  }
153
151
  }
154
152
 
155
- $field_markup_classes = $is_button_inside ? $border_color_classes : '';
156
- $field_markup = sprintf(
157
- '<div class="wp-block-search__inside-wrapper %s" %s>%s</div>',
158
- esc_attr( $field_markup_classes ),
153
+ $field_markup_classes = array(
154
+ 'wp-block-search__inside-wrapper',
155
+ );
156
+ if ( $is_button_inside && ! empty( $border_color_classes ) ) {
157
+ $field_markup_classes[] = $border_color_classes;
158
+ }
159
+ $field_markup = sprintf(
160
+ '<div class="%s" %s>%s</div>',
161
+ esc_attr( implode( ' ', $field_markup_classes ) ),
159
162
  $inline_styles['wrapper'],
160
163
  $input . $query_params_markup . $button
161
164
  );
162
- $wrapper_attributes = get_block_wrapper_attributes(
165
+ $wrapper_attributes = get_block_wrapper_attributes(
163
166
  array( 'class' => $classnames )
164
167
  );
165
- $form_directives = '';
168
+ $form_directives = '';
166
169
 
167
170
  // If it's interactive, add the directives.
168
171
  if ( $is_expandable_searchfield ) {
@@ -110,6 +110,7 @@ $button-spacing-y: math.div($grid-unit-15, 2); // 6px
110
110
  :where(.wp-block-search__button-inside .wp-block-search__inside-wrapper) {
111
111
  padding: $grid-unit-05;
112
112
  border: 1px solid $gray-600;
113
+ background-color: $white;
113
114
  box-sizing: border-box;
114
115
 
115
116
  .wp-block-search__input {
@@ -56,7 +56,7 @@ export default function SiteTitleEdit( {
56
56
 
57
57
  function setTitle( newTitle ) {
58
58
  editEntityRecord( 'root', 'site', undefined, {
59
- title: newTitle,
59
+ title: newTitle.trim(),
60
60
  } );
61
61
  }
62
62
 
@@ -16,7 +16,7 @@
16
16
  */
17
17
  function render_block_core_site_title( $attributes ) {
18
18
  $site_title = get_bloginfo( 'name' );
19
- if ( ! $site_title ) {
19
+ if ( ! trim( $site_title ) ) {
20
20
  return;
21
21
  }
22
22
 
@@ -6,7 +6,7 @@ import clsx from 'clsx';
6
6
  /**
7
7
  * WordPress dependencies
8
8
  */
9
- import { useEffect, useRef } from '@wordpress/element';
9
+ import { useEffect } from '@wordpress/element';
10
10
  import {
11
11
  BlockControls,
12
12
  useInnerBlocksProps,
@@ -57,16 +57,21 @@ export function SocialLinksEdit( props ) {
57
57
 
58
58
  const {
59
59
  iconBackgroundColorValue,
60
- customIconBackgroundColor,
61
60
  iconColorValue,
62
61
  openInNewTab,
63
62
  showLabels,
64
63
  size,
65
64
  } = attributes;
66
65
 
67
- const hasSelectedChild = useSelect(
68
- ( select ) =>
69
- select( blockEditorStore ).hasSelectedInnerBlock( clientId ),
66
+ const { hasSocialIcons, hasSelectedChild } = useSelect(
67
+ ( select ) => {
68
+ const { getBlockCount, hasSelectedInnerBlock } =
69
+ select( blockEditorStore );
70
+ return {
71
+ hasSocialIcons: getBlockCount( clientId ) > 0,
72
+ hasSelectedChild: hasSelectedInnerBlock( clientId ),
73
+ };
74
+ },
70
75
  [ clientId ]
71
76
  );
72
77
 
@@ -78,33 +83,25 @@ export function SocialLinksEdit( props ) {
78
83
 
79
84
  // Remove icon background color when logos only style is selected or
80
85
  // restore it when any other style is selected.
81
- const backgroundBackupRef = useRef( {} );
82
86
  useEffect( () => {
83
87
  if ( logosOnly ) {
84
- backgroundBackupRef.current = {
85
- iconBackgroundColor,
86
- iconBackgroundColorValue,
87
- customIconBackgroundColor,
88
- };
89
- setAttributes( {
90
- iconBackgroundColor: undefined,
91
- customIconBackgroundColor: undefined,
92
- iconBackgroundColorValue: undefined,
88
+ let restore;
89
+ setAttributes( ( prev ) => {
90
+ restore = {
91
+ iconBackgroundColor: prev.iconBackgroundColor,
92
+ iconBackgroundColorValue: prev.iconBackgroundColorValue,
93
+ customIconBackgroundColor: prev.customIconBackgroundColor,
94
+ };
95
+ return {
96
+ iconBackgroundColor: undefined,
97
+ iconBackgroundColorValue: undefined,
98
+ customIconBackgroundColor: undefined,
99
+ };
93
100
  } );
94
- } else {
95
- setAttributes( { ...backgroundBackupRef.current } );
96
- }
97
- }, [ logosOnly ] );
98
101
 
99
- const SocialPlaceholder = (
100
- <li className="wp-block-social-links__social-placeholder">
101
- <div className="wp-block-social-links__social-placeholder-icons">
102
- <div className="wp-social-link wp-social-link-twitter"></div>
103
- <div className="wp-social-link wp-social-link-facebook"></div>
104
- <div className="wp-social-link wp-social-link-instagram"></div>
105
- </div>
106
- </li>
107
- );
102
+ return () => setAttributes( { ...restore } );
103
+ }
104
+ }, [ logosOnly, setAttributes ] );
108
105
 
109
106
  // Fallback color values are used maintain selections in case switching
110
107
  // themes and named colors in palette do not match.
@@ -117,11 +114,13 @@ export function SocialLinksEdit( props ) {
117
114
 
118
115
  const blockProps = useBlockProps( { className } );
119
116
  const innerBlocksProps = useInnerBlocksProps( blockProps, {
120
- placeholder: ! isSelected && SocialPlaceholder,
121
117
  templateLock: false,
122
118
  orientation: attributes.layout?.orientation ?? 'horizontal',
123
119
  __experimentalAppenderTagName: 'li',
124
- renderAppender: hasAnySelected && InnerBlocks.ButtonBlockAppender,
120
+ renderAppender:
121
+ ! hasSocialIcons || hasAnySelected
122
+ ? InnerBlocks.ButtonBlockAppender
123
+ : undefined,
125
124
  } );
126
125
 
127
126
  const POPOVER_PROPS = {
@@ -12,67 +12,9 @@
12
12
 
13
13
  // Specificity for the following styles are fixed at 0-1-0 to match and be
14
14
  // overridable by global styles.
15
- :root :where(.wp-block-social-links),
16
- :root :where(.wp-block-social-links.is-style-logos-only .wp-block-social-links__social-placeholder .wp-social-link) {
15
+ :root :where(.wp-block-social-links) {
17
16
  padding: 0;
18
17
  }
19
- :root :where(.wp-block-social-links__social-placeholder .wp-social-link) {
20
- padding: 0.25em;
21
- }
22
- :root :where(.wp-block-social-links.is-style-pill-shape .wp-block-social-links__social-placeholder .wp-social-link) {
23
- padding-left: calc((2/3) * 1em);
24
- padding-right: calc((2/3) * 1em);
25
- }
26
-
27
- // Placeholder/setup state.
28
- .wp-block-social-links__social-placeholder {
29
- display: flex;
30
- opacity: 0.8;
31
- list-style: none;
32
-
33
- // Use the first link to set the height.
34
- > .wp-social-link {
35
- // Use !important to keep the selector simple.
36
- padding-left: 0 !important;
37
- margin-left: 0 !important;
38
- padding-right: 0 !important;
39
- margin-right: 0 !important;
40
- width: 0 !important;
41
- visibility: hidden;
42
- }
43
-
44
- // Wrap the remaining placeholders in a container so the plus can overlap.
45
- > .wp-block-social-links__social-placeholder-icons {
46
- display: flex;
47
- }
48
-
49
- .wp-social-link::before {
50
- content: "";
51
- display: block;
52
- width: 1em;
53
- height: 1em;
54
- border-radius: $radius-round;
55
-
56
- .is-style-logos-only & {
57
- background: currentColor;
58
- }
59
- }
60
- }
61
-
62
- // Selected placeholder state.
63
- .wp-block-social-links .wp-block-social-links__social-prompt {
64
- min-height: $button-size-small;
65
- list-style: none;
66
-
67
- // Show as block UI.
68
- font-family: $default-font;
69
- font-size: $default-font-size;
70
- line-height: $button-size-small;
71
- margin-top: auto;
72
- margin-bottom: auto;
73
- cursor: default;
74
- padding-right: $grid-unit-10;
75
- }
76
18
 
77
19
  // Center flex items. This has an equivalent in style.scss.
78
20
  .wp-block[data-align="center"] > .wp-block-social-links,
@@ -48,7 +48,7 @@ export const settings = {
48
48
  tag: 'td',
49
49
  },
50
50
  {
51
- content: 'Jaco Pastorius',
51
+ content: __( 'Jaco Pastorius' ),
52
52
  tag: 'td',
53
53
  },
54
54
  {
@@ -64,7 +64,7 @@ export const settings = {
64
64
  tag: 'td',
65
65
  },
66
66
  {
67
- content: 'Betty Carter',
67
+ content: __( 'Betty Carter' ),
68
68
  tag: 'td',
69
69
  },
70
70
  {
@@ -80,7 +80,7 @@ export const settings = {
80
80
  tag: 'td',
81
81
  },
82
82
  {
83
- content: 'Bebo Valdés',
83
+ content: __( 'Bebo Valdés' ),
84
84
  tag: 'td',
85
85
  },
86
86
  {
@@ -15,12 +15,12 @@ const tableContentPasteSchema = ( { phrasingContentSchema } ) => ( {
15
15
  th: {
16
16
  allowEmpty: true,
17
17
  children: phrasingContentSchema,
18
- attributes: [ 'scope', 'colspan', 'rowspan' ],
18
+ attributes: [ 'scope', 'colspan', 'rowspan', 'style' ],
19
19
  },
20
20
  td: {
21
21
  allowEmpty: true,
22
22
  children: phrasingContentSchema,
23
- attributes: [ 'colspan', 'rowspan' ],
23
+ attributes: [ 'colspan', 'rowspan', 'style' ],
24
24
  },
25
25
  },
26
26
  },
@@ -79,11 +79,23 @@ const transforms = {
79
79
  col.getAttribute( 'colspan' )
80
80
  );
81
81
 
82
+ const { textAlign } = col.style || {};
83
+
84
+ let align;
85
+ if (
86
+ textAlign === 'left' ||
87
+ textAlign === 'center' ||
88
+ textAlign === 'right'
89
+ ) {
90
+ align = textAlign;
91
+ }
92
+
82
93
  colAcc.push( {
83
94
  tag: col.nodeName.toLowerCase(),
84
95
  content: col.innerHTML,
85
96
  rowspan,
86
97
  colspan,
98
+ align,
87
99
  } );
88
100
 
89
101
  return colAcc;
@@ -19,6 +19,9 @@
19
19
  "onlyIncludeCurrentPage": {
20
20
  "type": "boolean",
21
21
  "default": false
22
+ },
23
+ "maxLevel": {
24
+ "type": "number"
22
25
  }
23
26
  },
24
27
  "supports": {
@@ -12,6 +12,7 @@ import { createBlock } from '@wordpress/blocks';
12
12
  import {
13
13
  Placeholder,
14
14
  ToggleControl,
15
+ SelectControl,
15
16
  ToolbarButton,
16
17
  ToolbarGroup,
17
18
  __experimentalToolsPanel as ToolsPanel,
@@ -39,15 +40,16 @@ import { useToolsPanelDropdownMenuProps } from '../utils/hooks';
39
40
  *
40
41
  * @param {Object} props The props.
41
42
  * @param {Object} props.attributes The block attributes.
42
- * @param {HeadingData[]} props.attributes.headings A list of data for each heading in the post.
43
+ * @param {HeadingData[]} props.attributes.headings The list of data for each heading in the post.
43
44
  * @param {boolean} props.attributes.onlyIncludeCurrentPage Whether to only include headings from the current page (if the post is paginated).
44
- * @param {string} props.clientId
45
- * @param {(attributes: Object) => void} props.setAttributes
45
+ * @param {number|undefined} props.attributes.maxLevel The maximum heading level to include, or null to include all levels.
46
+ * @param {string} props.clientId The client id.
47
+ * @param {(attributes: Object) => void} props.setAttributes The set attributes function.
46
48
  *
47
49
  * @return {Component} The component.
48
50
  */
49
51
  export default function TableOfContentsEdit( {
50
- attributes: { headings = [], onlyIncludeCurrentPage },
52
+ attributes: { headings = [], onlyIncludeCurrentPage, maxLevel },
51
53
  clientId,
52
54
  setAttributes,
53
55
  } ) {
@@ -115,6 +117,7 @@ export default function TableOfContentsEdit( {
115
117
  resetAll={ () => {
116
118
  setAttributes( {
117
119
  onlyIncludeCurrentPage: false,
120
+ maxLevel: undefined,
118
121
  } );
119
122
  } }
120
123
  dropdownMenuProps={ dropdownMenuProps }
@@ -145,6 +148,44 @@ export default function TableOfContentsEdit( {
145
148
  }
146
149
  />
147
150
  </ToolsPanelItem>
151
+ <ToolsPanelItem
152
+ hasValue={ () => !! maxLevel }
153
+ label={ __( 'Limit heading levels' ) }
154
+ onDeselect={ () =>
155
+ setAttributes( { maxLevel: undefined } )
156
+ }
157
+ isShownByDefault
158
+ >
159
+ <SelectControl
160
+ __nextHasNoMarginBottom
161
+ __next40pxDefaultSize
162
+ label={ __( 'Include headings down to level' ) }
163
+ value={ maxLevel || '' }
164
+ options={ [
165
+ { value: '', label: __( 'All levels' ) },
166
+ { value: '1', label: __( 'Heading 1' ) },
167
+ { value: '2', label: __( 'Heading 2' ) },
168
+ { value: '3', label: __( 'Heading 3' ) },
169
+ { value: '4', label: __( 'Heading 4' ) },
170
+ { value: '5', label: __( 'Heading 5' ) },
171
+ { value: '6', label: __( 'Heading 6' ) },
172
+ ] }
173
+ onChange={ ( value ) =>
174
+ setAttributes( {
175
+ maxLevel: value ? parseInt( value ) : undefined,
176
+ } )
177
+ }
178
+ help={
179
+ ! maxLevel
180
+ ? __(
181
+ 'Including all heading levels in the table of contents.'
182
+ )
183
+ : __(
184
+ 'Only include headings up to and including this level.'
185
+ )
186
+ }
187
+ />
188
+ </ToolsPanelItem>
148
189
  </ToolsPanel>
149
190
  </InspectorControls>
150
191
  );
@@ -29,7 +29,8 @@ function getLatestHeadings( select, clientId ) {
29
29
  const permalink = select( 'core/editor' ).getPermalink() ?? null;
30
30
 
31
31
  const isPaginated = getBlocksByName( 'core/nextpage' ).length !== 0;
32
- const { onlyIncludeCurrentPage } = getBlockAttributes( clientId ) ?? {};
32
+ const { onlyIncludeCurrentPage, maxLevel } =
33
+ getBlockAttributes( clientId ) ?? {};
33
34
 
34
35
  // Get post-content block client ID.
35
36
  const [ postContentClientId = '' ] = getBlocksByName( 'core/post-content' );
@@ -100,6 +101,11 @@ function getLatestHeadings( select, clientId ) {
100
101
  if ( blockName === 'core/heading' ) {
101
102
  const headingAttributes = getBlockAttributes( blockClientId );
102
103
 
104
+ // Skip headings that are deeper than maxLevel
105
+ if ( maxLevel && headingAttributes.level > maxLevel ) {
106
+ continue;
107
+ }
108
+
103
109
  const canBeLinked =
104
110
  typeof headingPageLink === 'string' &&
105
111
  typeof headingAttributes.anchor === 'string' &&
@@ -142,8 +148,11 @@ function observeCallback( select, dispatch, clientId ) {
142
148
 
143
149
  const headings = getLatestHeadings( select, clientId );
144
150
  if ( ! fastDeepEqual( headings, attributes.headings ) ) {
145
- __unstableMarkNextChangeAsNotPersistent();
146
- updateBlockAttributes( clientId, { headings } );
151
+ // Executing the update in a microtask ensures that the non-persistent marker doesn't affect an attribute triggering the change.
152
+ window.queueMicrotask( () => {
153
+ __unstableMarkNextChangeAsNotPersistent();
154
+ updateBlockAttributes( clientId, { headings } );
155
+ } );
147
156
  }
148
157
  }
149
158
 
@@ -7,11 +7,6 @@
7
7
  justify-content: center;
8
8
  }
9
9
 
10
- &.alignfull {
11
- padding-left: 1em;
12
- padding-right: 1em;
13
- }
14
-
15
10
  a {
16
11
  display: inline-block;
17
12
  margin-right: 5px;