@wordpress/block-library 9.35.1-next.16d95556a.0 → 9.36.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 (311) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/build/accordion/view.js +46 -4
  3. package/build/accordion/view.js.map +2 -2
  4. package/build/accordion-heading/block.json +1 -1
  5. package/build/accordion-heading/deprecated.js +1 -1
  6. package/build/accordion-heading/deprecated.js.map +2 -2
  7. package/build/accordion-panel/block.json +1 -1
  8. package/build/audio/index.js +29 -0
  9. package/build/audio/index.js.map +3 -3
  10. package/build/breadcrumbs/edit.js +1 -1
  11. package/build/breadcrumbs/edit.js.map +2 -2
  12. package/build/button/index.js +25 -0
  13. package/build/button/index.js.map +3 -3
  14. package/build/code/index.js +15 -0
  15. package/build/code/index.js.map +3 -3
  16. package/build/cover/edit/block-controls.js +37 -3
  17. package/build/cover/edit/block-controls.js.map +3 -3
  18. package/build/cover/edit/cover-placeholder.js +0 -1
  19. package/build/cover/edit/cover-placeholder.js.map +2 -2
  20. package/build/cover/edit/embed-video-url-input.js +83 -0
  21. package/build/cover/edit/embed-video-url-input.js.map +7 -0
  22. package/build/cover/edit/index.js +60 -0
  23. package/build/cover/edit/index.js.map +2 -2
  24. package/build/cover/embed-video-utils.js +151 -0
  25. package/build/cover/embed-video-utils.js.map +7 -0
  26. package/build/cover/index.js +28 -0
  27. package/build/cover/index.js.map +3 -3
  28. package/build/cover/save.js +12 -0
  29. package/build/cover/save.js.map +2 -2
  30. package/build/cover/shared.js +3 -0
  31. package/build/cover/shared.js.map +2 -2
  32. package/build/details/index.js +15 -0
  33. package/build/details/index.js.map +3 -3
  34. package/build/file/index.js +33 -0
  35. package/build/file/index.js.map +3 -3
  36. package/build/freeform/block.json +1 -1
  37. package/build/gallery/edit.js +0 -2
  38. package/build/gallery/edit.js.map +2 -2
  39. package/build/heading/index.js +15 -0
  40. package/build/heading/index.js.map +3 -3
  41. package/build/html/modal.js +139 -148
  42. package/build/html/modal.js.map +3 -3
  43. package/build/image/edit.js +0 -1
  44. package/build/image/edit.js.map +2 -2
  45. package/build/image/image.js +0 -1
  46. package/build/image/image.js.map +2 -2
  47. package/build/image/index.js +46 -0
  48. package/build/image/index.js.map +3 -3
  49. package/build/list-item/index.js +15 -0
  50. package/build/list-item/index.js.map +3 -3
  51. package/build/math/block.json +28 -1
  52. package/build/math/edit.js +4 -1
  53. package/build/math/edit.js.map +2 -2
  54. package/build/media-text/index.js +35 -0
  55. package/build/media-text/index.js.map +3 -3
  56. package/build/media-text/media-container.js +0 -2
  57. package/build/media-text/media-container.js.map +2 -2
  58. package/build/missing/block.json +1 -1
  59. package/build/missing/edit.js +2 -2
  60. package/build/missing/edit.js.map +1 -1
  61. package/build/more/index.js +16 -0
  62. package/build/more/index.js.map +3 -3
  63. package/build/navigation/block.json +2 -2
  64. package/build/navigation-link/block.json +2 -1
  65. package/build/navigation-link/edit.js +42 -11
  66. package/build/navigation-link/edit.js.map +2 -2
  67. package/build/navigation-link/index.js +25 -0
  68. package/build/navigation-link/index.js.map +3 -3
  69. package/build/navigation-link/shared/controls.js +15 -19
  70. package/build/navigation-link/shared/controls.js.map +2 -2
  71. package/build/navigation-link/shared/index.js +4 -0
  72. package/build/navigation-link/shared/index.js.map +2 -2
  73. package/build/navigation-link/shared/use-entity-binding.js +3 -2
  74. package/build/navigation-link/shared/use-entity-binding.js.map +2 -2
  75. package/build/navigation-submenu/block.json +2 -1
  76. package/build/navigation-submenu/index.js +25 -0
  77. package/build/navigation-submenu/index.js.map +3 -3
  78. package/build/paragraph/deprecated-attributes.js +68 -0
  79. package/build/paragraph/deprecated-attributes.js.map +7 -0
  80. package/build/paragraph/edit.js +2 -0
  81. package/build/paragraph/edit.js.map +3 -3
  82. package/build/paragraph/index.js +15 -0
  83. package/build/paragraph/index.js.map +3 -3
  84. package/build/pattern/block.json +1 -1
  85. package/build/post-comments-count/edit.js +1 -2
  86. package/build/post-comments-count/edit.js.map +2 -2
  87. package/build/post-comments-link/edit.js +10 -7
  88. package/build/post-comments-link/edit.js.map +2 -2
  89. package/build/preformatted/index.js +15 -0
  90. package/build/preformatted/index.js.map +3 -3
  91. package/build/pullquote/index.js +20 -0
  92. package/build/pullquote/index.js.map +3 -3
  93. package/build/search/index.js +26 -0
  94. package/build/search/index.js.map +3 -3
  95. package/build/social-link/index.js +25 -0
  96. package/build/social-link/index.js.map +3 -3
  97. package/build/social-links/edit.js +1 -1
  98. package/build/social-links/edit.js.map +1 -1
  99. package/build/tabs/view.js +17 -4
  100. package/build/tabs/view.js.map +2 -2
  101. package/build/template-part/edit/index.js +37 -7
  102. package/build/template-part/edit/index.js.map +2 -2
  103. package/build/template-part/edit/utils/hooks.js +2 -3
  104. package/build/template-part/edit/utils/hooks.js.map +2 -2
  105. package/build/term-count/index.js +1 -0
  106. package/build/term-count/index.js.map +2 -2
  107. package/build/term-name/index.js +1 -0
  108. package/build/term-name/index.js.map +2 -2
  109. package/build/verse/index.js +15 -0
  110. package/build/verse/index.js.map +3 -3
  111. package/build/video/index.js +30 -0
  112. package/build/video/index.js.map +3 -3
  113. package/build-module/accordion/view.js +46 -4
  114. package/build-module/accordion/view.js.map +2 -2
  115. package/build-module/accordion-heading/block.json +1 -1
  116. package/build-module/accordion-heading/deprecated.js +1 -1
  117. package/build-module/accordion-heading/deprecated.js.map +2 -2
  118. package/build-module/accordion-panel/block.json +1 -1
  119. package/build-module/audio/index.js +29 -0
  120. package/build-module/audio/index.js.map +2 -2
  121. package/build-module/breadcrumbs/edit.js +1 -1
  122. package/build-module/breadcrumbs/edit.js.map +2 -2
  123. package/build-module/button/index.js +25 -0
  124. package/build-module/button/index.js.map +2 -2
  125. package/build-module/code/index.js +15 -0
  126. package/build-module/code/index.js.map +2 -2
  127. package/build-module/cover/edit/block-controls.js +27 -3
  128. package/build-module/cover/edit/block-controls.js.map +2 -2
  129. package/build-module/cover/edit/cover-placeholder.js +0 -1
  130. package/build-module/cover/edit/cover-placeholder.js.map +2 -2
  131. package/build-module/cover/edit/embed-video-url-input.js +67 -0
  132. package/build-module/cover/edit/embed-video-url-input.js.map +7 -0
  133. package/build-module/cover/edit/index.js +61 -0
  134. package/build-module/cover/edit/index.js.map +2 -2
  135. package/build-module/cover/embed-video-utils.js +122 -0
  136. package/build-module/cover/embed-video-utils.js.map +7 -0
  137. package/build-module/cover/index.js +28 -0
  138. package/build-module/cover/index.js.map +2 -2
  139. package/build-module/cover/save.js +13 -0
  140. package/build-module/cover/save.js.map +2 -2
  141. package/build-module/cover/shared.js +2 -0
  142. package/build-module/cover/shared.js.map +2 -2
  143. package/build-module/details/index.js +15 -0
  144. package/build-module/details/index.js.map +2 -2
  145. package/build-module/file/index.js +34 -1
  146. package/build-module/file/index.js.map +2 -2
  147. package/build-module/freeform/block.json +1 -1
  148. package/build-module/gallery/edit.js +0 -2
  149. package/build-module/gallery/edit.js.map +2 -2
  150. package/build-module/heading/index.js +15 -0
  151. package/build-module/heading/index.js.map +2 -2
  152. package/build-module/html/modal.js +141 -150
  153. package/build-module/html/modal.js.map +2 -2
  154. package/build-module/image/edit.js +0 -1
  155. package/build-module/image/edit.js.map +2 -2
  156. package/build-module/image/image.js +0 -1
  157. package/build-module/image/image.js.map +2 -2
  158. package/build-module/image/index.js +46 -0
  159. package/build-module/image/index.js.map +2 -2
  160. package/build-module/list-item/index.js +15 -0
  161. package/build-module/list-item/index.js.map +2 -2
  162. package/build-module/math/block.json +28 -1
  163. package/build-module/math/edit.js +4 -1
  164. package/build-module/math/edit.js.map +2 -2
  165. package/build-module/media-text/index.js +35 -0
  166. package/build-module/media-text/index.js.map +2 -2
  167. package/build-module/media-text/media-container.js +0 -2
  168. package/build-module/media-text/media-container.js.map +2 -2
  169. package/build-module/missing/block.json +1 -1
  170. package/build-module/missing/edit.js +2 -2
  171. package/build-module/missing/edit.js.map +1 -1
  172. package/build-module/more/index.js +16 -0
  173. package/build-module/more/index.js.map +2 -2
  174. package/build-module/navigation/block.json +2 -2
  175. package/build-module/navigation-link/block.json +2 -1
  176. package/build-module/navigation-link/edit.js +56 -15
  177. package/build-module/navigation-link/edit.js.map +2 -2
  178. package/build-module/navigation-link/index.js +26 -1
  179. package/build-module/navigation-link/index.js.map +2 -2
  180. package/build-module/navigation-link/shared/controls.js +12 -18
  181. package/build-module/navigation-link/shared/controls.js.map +2 -2
  182. package/build-module/navigation-link/shared/index.js +3 -1
  183. package/build-module/navigation-link/shared/index.js.map +2 -2
  184. package/build-module/navigation-link/shared/use-entity-binding.js +3 -2
  185. package/build-module/navigation-link/shared/use-entity-binding.js.map +2 -2
  186. package/build-module/navigation-submenu/block.json +2 -1
  187. package/build-module/navigation-submenu/index.js +26 -1
  188. package/build-module/navigation-submenu/index.js.map +2 -2
  189. package/build-module/paragraph/deprecated-attributes.js +37 -0
  190. package/build-module/paragraph/deprecated-attributes.js.map +7 -0
  191. package/build-module/paragraph/edit.js +2 -0
  192. package/build-module/paragraph/edit.js.map +2 -2
  193. package/build-module/paragraph/index.js +15 -0
  194. package/build-module/paragraph/index.js.map +2 -2
  195. package/build-module/pattern/block.json +1 -1
  196. package/build-module/post-comments-count/edit.js +1 -3
  197. package/build-module/post-comments-count/edit.js.map +2 -2
  198. package/build-module/post-comments-link/edit.js +10 -8
  199. package/build-module/post-comments-link/edit.js.map +2 -2
  200. package/build-module/preformatted/index.js +15 -0
  201. package/build-module/preformatted/index.js.map +2 -2
  202. package/build-module/pullquote/index.js +20 -0
  203. package/build-module/pullquote/index.js.map +2 -2
  204. package/build-module/search/index.js +26 -0
  205. package/build-module/search/index.js.map +2 -2
  206. package/build-module/social-link/index.js +25 -0
  207. package/build-module/social-link/index.js.map +2 -2
  208. package/build-module/social-links/edit.js +1 -1
  209. package/build-module/social-links/edit.js.map +1 -1
  210. package/build-module/tabs/view.js +17 -4
  211. package/build-module/tabs/view.js.map +2 -2
  212. package/build-module/template-part/edit/index.js +37 -7
  213. package/build-module/template-part/edit/index.js.map +2 -2
  214. package/build-module/template-part/edit/utils/hooks.js +2 -3
  215. package/build-module/template-part/edit/utils/hooks.js.map +2 -2
  216. package/build-module/term-count/index.js +1 -0
  217. package/build-module/term-count/index.js.map +2 -2
  218. package/build-module/term-name/index.js +1 -0
  219. package/build-module/term-name/index.js.map +2 -2
  220. package/build-module/verse/index.js +15 -0
  221. package/build-module/verse/index.js.map +2 -2
  222. package/build-module/video/index.js +30 -0
  223. package/build-module/video/index.js.map +2 -2
  224. package/build-style/accordion/style-rtl.css +3 -0
  225. package/build-style/accordion/style.css +3 -0
  226. package/build-style/accordion-heading/style-rtl.css +1 -2
  227. package/build-style/accordion-heading/style.css +1 -2
  228. package/build-style/accordion-item/style-rtl.css +0 -7
  229. package/build-style/accordion-item/style.css +0 -7
  230. package/build-style/accordion-panel/style-rtl.css +1 -4
  231. package/build-style/accordion-panel/style.css +1 -4
  232. package/build-style/cover/style-rtl.css +47 -0
  233. package/build-style/cover/style.css +47 -0
  234. package/build-style/editor-rtl.css +11 -13
  235. package/build-style/editor.css +11 -13
  236. package/build-style/html/editor-rtl.css +11 -13
  237. package/build-style/html/editor.css +11 -13
  238. package/build-style/style-rtl.css +52 -12
  239. package/build-style/style.css +52 -12
  240. package/package.json +37 -37
  241. package/src/accordion/style.scss +4 -0
  242. package/src/accordion/view.js +60 -3
  243. package/src/accordion-heading/block.json +1 -1
  244. package/src/accordion-heading/deprecated.js +1 -1
  245. package/src/accordion-heading/style.scss +1 -9
  246. package/src/accordion-item/index.php +1 -0
  247. package/src/accordion-item/style.scss +2 -9
  248. package/src/accordion-panel/block.json +1 -1
  249. package/src/accordion-panel/style.scss +1 -5
  250. package/src/audio/index.js +31 -0
  251. package/src/breadcrumbs/edit.js +4 -2
  252. package/src/breadcrumbs/index.php +171 -100
  253. package/src/button/index.js +27 -0
  254. package/src/code/index.js +17 -0
  255. package/src/cover/edit/block-controls.js +26 -2
  256. package/src/cover/edit/cover-placeholder.js +0 -1
  257. package/src/cover/edit/embed-video-url-input.js +74 -0
  258. package/src/cover/edit/index.js +81 -0
  259. package/src/cover/embed-video-utils.js +196 -0
  260. package/src/cover/index.js +30 -0
  261. package/src/cover/index.php +106 -0
  262. package/src/cover/save.js +14 -0
  263. package/src/cover/shared.js +1 -0
  264. package/src/cover/style.scss +47 -0
  265. package/src/details/index.js +17 -0
  266. package/src/file/index.js +36 -1
  267. package/src/freeform/block.json +1 -1
  268. package/src/gallery/edit.js +0 -2
  269. package/src/heading/index.js +17 -0
  270. package/src/html/editor.scss +10 -15
  271. package/src/html/modal.js +23 -38
  272. package/src/image/edit.js +0 -1
  273. package/src/image/image.js +0 -1
  274. package/src/image/index.js +48 -0
  275. package/src/image/index.php +1 -0
  276. package/src/list-item/index.js +17 -0
  277. package/src/math/block.json +28 -1
  278. package/src/math/edit.js +4 -1
  279. package/src/media-text/index.js +37 -0
  280. package/src/media-text/media-container.js +0 -2
  281. package/src/missing/block.json +1 -1
  282. package/src/missing/edit.js +2 -2
  283. package/src/more/index.js +18 -0
  284. package/src/navigation/block.json +2 -2
  285. package/src/navigation-link/block.json +2 -1
  286. package/src/navigation-link/edit.js +98 -29
  287. package/src/navigation-link/index.js +28 -1
  288. package/src/navigation-link/shared/controls.js +13 -17
  289. package/src/navigation-link/shared/index.js +1 -1
  290. package/src/navigation-link/shared/use-entity-binding.js +5 -2
  291. package/src/navigation-submenu/block.json +2 -1
  292. package/src/navigation-submenu/index.js +28 -1
  293. package/src/paragraph/deprecated-attributes.js +45 -0
  294. package/src/paragraph/edit.js +2 -0
  295. package/src/paragraph/index.js +17 -0
  296. package/src/pattern/block.json +1 -1
  297. package/src/post-comments-count/edit.js +1 -9
  298. package/src/post-comments-link/edit.js +8 -18
  299. package/src/preformatted/index.js +17 -0
  300. package/src/pullquote/index.js +22 -0
  301. package/src/search/index.js +28 -0
  302. package/src/social-link/index.js +27 -0
  303. package/src/social-links/edit.js +1 -1
  304. package/src/style.scss +1 -0
  305. package/src/tabs/view.js +19 -4
  306. package/src/template-part/edit/index.js +44 -6
  307. package/src/template-part/edit/utils/hooks.js +2 -4
  308. package/src/term-count/index.js +1 -0
  309. package/src/term-name/index.js +1 -0
  310. package/src/verse/index.js +17 -0
  311. package/src/video/index.js +32 -0
@@ -8,7 +8,7 @@
8
8
  /**
9
9
  * Renders the `core/breadcrumbs` block on the server.
10
10
  *
11
- * @since 6.9.0
11
+ * @since 7.0.0
12
12
  *
13
13
  * @param array $attributes Block attributes.
14
14
  * @param string $content Block default content.
@@ -26,9 +26,9 @@ function render_block_core_breadcrumbs( $attributes, $content, $block ) {
26
26
 
27
27
  if ( $attributes['showHomeLink'] ) {
28
28
  if ( ! $is_home_or_front_page ) {
29
- $breadcrumb_items[] = block_core_breadcrumbs_create_link(
30
- home_url( '/' ),
31
- __( 'Home' )
29
+ $breadcrumb_items[] = array(
30
+ 'label' => __( 'Home' ),
31
+ 'url' => home_url( '/' ),
32
32
  );
33
33
  } else {
34
34
  $breadcrumb_items[] = block_core_breadcrumbs_create_item( __( 'Home' ), block_core_breadcrumbs_is_paged() );
@@ -53,8 +53,8 @@ function render_block_core_breadcrumbs( $attributes, $content, $block ) {
53
53
  }
54
54
  } elseif ( is_404() ) {
55
55
  // Handle 404 pages.
56
- $breadcrumb_items[] = block_core_breadcrumbs_create_current_item(
57
- __( 'Page not found' )
56
+ $breadcrumb_items[] = array(
57
+ 'label' => __( 'Page not found' ),
58
58
  );
59
59
  } elseif ( is_archive() ) {
60
60
  // Handle archive pages (taxonomy, post type, date, author archives).
@@ -76,25 +76,71 @@ function render_block_core_breadcrumbs( $attributes, $content, $block ) {
76
76
  return '';
77
77
  }
78
78
 
79
- // Determine breadcrumb type for accurate rendering (matching JavaScript logic).
79
+ // For non-hierarchical post types with parents (e.g., attachments), build trail for the parent.
80
+ $post_parent = $post->post_parent;
81
+ $parent_post = null;
82
+ if ( ! is_post_type_hierarchical( $post_type ) && $post_parent ) {
83
+ $parent_post = get_post( $post_parent );
84
+ if ( $parent_post ) {
85
+ $post_id = $parent_post->ID;
86
+ $post_type = $parent_post->post_type;
87
+ $post_parent = $parent_post->post_parent;
88
+ }
89
+ }
90
+
91
+ // Determine breadcrumb type.
92
+ // Some non-hierarchical post types (e.g., attachments) can have parents.
93
+ // Use hierarchical breadcrumbs if a parent exists, otherwise use taxonomy breadcrumbs.
80
94
  $show_terms = false;
81
- if ( ! is_post_type_hierarchical( $post_type ) ) {
95
+ if ( ! is_post_type_hierarchical( $post_type ) && ! $post_parent ) {
82
96
  $show_terms = true;
83
97
  } elseif ( empty( get_object_taxonomies( $post_type, 'objects' ) ) ) {
84
- // Hierarchical post type without taxonomies can only use ancestors.
85
98
  $show_terms = false;
86
99
  } else {
87
- // For hierarchical post types with taxonomies, use the attribute.
88
100
  $show_terms = $attributes['prefersTaxonomy'];
89
101
  }
90
102
 
103
+ // Add post type archive link if applicable.
104
+ $post_type_object = get_post_type_object( $post_type );
105
+ $archive_link = get_post_type_archive_link( $post_type );
106
+ if ( $archive_link && untrailingslashit( home_url() ) !== untrailingslashit( $archive_link ) ) {
107
+ $label = $post_type_object->labels->archives;
108
+ if ( 'post' === $post_type ) {
109
+ $page_for_posts = get_option( 'page_for_posts' );
110
+ if ( $page_for_posts ) {
111
+ $label = block_core_breadcrumbs_get_post_title( $page_for_posts );
112
+ }
113
+ }
114
+ $breadcrumb_items[] = array(
115
+ 'label' => $label,
116
+ 'url' => $archive_link,
117
+ );
118
+ }
119
+ // Build breadcrumb trail based on hierarchical structure or taxonomy terms.
91
120
  if ( ! $show_terms ) {
92
121
  $breadcrumb_items = array_merge( $breadcrumb_items, block_core_breadcrumbs_get_hierarchical_post_type_breadcrumbs( $post_id ) );
93
122
  } else {
94
123
  $breadcrumb_items = array_merge( $breadcrumb_items, block_core_breadcrumbs_get_terms_breadcrumbs( $post_id, $post_type ) );
95
124
  }
96
- // Add current post title (not linked).
97
- $breadcrumb_items[] = block_core_breadcrumbs_create_current_item( block_core_breadcrumbs_get_post_title( $post ), true );
125
+
126
+ // Add post title: linked when viewing a paginated page, plain text otherwise.
127
+ $is_paged = (int) get_query_var( 'page' ) > 1;
128
+ $title = block_core_breadcrumbs_get_post_title( $post );
129
+
130
+ if ( $is_paged ) {
131
+ $breadcrumb_items[] = array(
132
+ 'label' => $title,
133
+ 'url' => get_permalink( $post ),
134
+ 'allow_html' => true,
135
+ );
136
+
137
+ $breadcrumb_items[] = block_core_breadcrumbs_create_page_number_item( 'page' );
138
+ } else {
139
+ $breadcrumb_items[] = array(
140
+ 'label' => $title,
141
+ 'allow_html' => true,
142
+ );
143
+ }
98
144
  }
99
145
 
100
146
  // Remove last item if disabled.
@@ -120,7 +166,11 @@ function render_block_core_breadcrumbs( $attributes, $content, $block ) {
120
166
  '',
121
167
  array_map(
122
168
  static function ( $item ) {
123
- return '<li>' . $item . '</li>';
169
+ $label = ! empty( $item['allow_html'] ) ? wp_kses_post( $item['label'] ) : esc_html( $item['label'] );
170
+ if ( ! empty( $item['url'] ) ) {
171
+ return '<li><a href="' . esc_url( $item['url'] ) . '">' . $label . '</a></li>';
172
+ }
173
+ return '<li><span aria-current="page">' . $label . '</span></li>';
124
174
  },
125
175
  $breadcrumb_items
126
176
  )
@@ -133,7 +183,7 @@ function render_block_core_breadcrumbs( $attributes, $content, $block ) {
133
183
  /**
134
184
  * Checks if we're on a paginated view (page 2 or higher).
135
185
  *
136
- * @since 6.9.0
186
+ * @since 7.0.0
137
187
  *
138
188
  * @return bool True if paged > 1, false otherwise.
139
189
  */
@@ -145,53 +195,22 @@ function block_core_breadcrumbs_is_paged() {
145
195
  /**
146
196
  * Creates a "Page X" breadcrumb item for paginated views.
147
197
  *
148
- * @since 6.9.0
149
- *
150
- * @return string The "Page X" breadcrumb HTML.
198
+ * @since 7.0.0
199
+ * @param string $query_var Optional. Query variable to get current page number. Default 'paged'.
200
+ * @return array The "Page X" breadcrumb item data.
151
201
  */
152
- function block_core_breadcrumbs_create_page_number_item() {
153
- $paged = (int) get_query_var( 'paged' );
154
- return block_core_breadcrumbs_create_current_item(
155
- /* translators: %s: page number */
156
- sprintf( __( 'Page %s' ), number_format_i18n( $paged ) )
202
+ function block_core_breadcrumbs_create_page_number_item( $query_var = 'paged' ) {
203
+ $paged = (int) get_query_var( $query_var );
204
+
205
+ return array(
206
+ 'label' => sprintf(
207
+ /* translators: %s: page number */
208
+ __( 'Page %s' ),
209
+ number_format_i18n( $paged )
210
+ ),
157
211
  );
158
212
  }
159
213
 
160
- /**
161
- * Creates a breadcrumb link item.
162
- *
163
- * @since 6.9.0
164
- *
165
- * @param string $url The URL for the link (will be escaped).
166
- * @param string $text The link text (will be escaped).
167
- * @param bool $allow_html Whether to allow HTML in the text. If true, uses wp_kses_post(), otherwise uses esc_html(). Default false.
168
- *
169
- * @return string The breadcrumb link HTML.
170
- */
171
- function block_core_breadcrumbs_create_link( $url, $text, $allow_html = false ) {
172
- return sprintf(
173
- '<a href="%s">%s</a>',
174
- esc_url( $url ),
175
- $allow_html ? wp_kses_post( $text ) : esc_html( $text )
176
- );
177
- }
178
-
179
- /**
180
- * Creates a breadcrumb current page item.
181
- *
182
- * @since 6.9.0
183
- *
184
- * @param string $text The text content (will be escaped).
185
- * @param bool $allow_html Whether to allow HTML in the text. If true, uses wp_kses_post(), otherwise uses esc_html(). Default false.
186
- *
187
- * @return string The breadcrumb current page HTML.
188
- */
189
- function block_core_breadcrumbs_create_current_item( $text, $allow_html = false ) {
190
- return sprintf(
191
- '<span aria-current="page">%s</span>',
192
- $allow_html ? wp_kses_post( $text ) : esc_html( $text )
193
- );
194
- }
195
214
 
196
215
  /**
197
216
  * Creates a breadcrumb item that's either a link or current page item.
@@ -199,25 +218,25 @@ function block_core_breadcrumbs_create_current_item( $text, $allow_html = false
199
218
  * When paginated (is_paged is true), creates a link to page 1.
200
219
  * Otherwise, creates a span marked as the current page.
201
220
  *
202
- * @since 6.9.0
221
+ * @since 7.0.0
203
222
  *
204
- * @param string $text The text content (will be escaped).
223
+ * @param string $text The text content.
205
224
  * @param bool $is_paged Whether we're on a paginated view.
206
- * @param bool $allow_html Whether to allow HTML in the text. If true, uses wp_kses_post(), otherwise uses esc_html(). Default false.
207
225
  *
208
- * @return string The breadcrumb HTML.
226
+ * @return array The breadcrumb item data.
209
227
  */
210
- function block_core_breadcrumbs_create_item( $text, $is_paged = false, $allow_html = false ) {
228
+ function block_core_breadcrumbs_create_item( $text, $is_paged = false ) {
229
+ $item = array( 'label' => $text );
211
230
  if ( $is_paged ) {
212
- return block_core_breadcrumbs_create_link( get_pagenum_link( 1 ), $text, $allow_html );
231
+ $item['url'] = get_pagenum_link( 1 );
213
232
  }
214
- return block_core_breadcrumbs_create_current_item( $text, $allow_html );
233
+ return $item;
215
234
  }
216
235
 
217
236
  /**
218
237
  * Gets a post title with fallback for empty titles.
219
238
  *
220
- * @since 6.9.0
239
+ * @since 7.0.0
221
240
  *
222
241
  * @param int|WP_Post $post_id_or_object The post ID or post object.
223
242
  *
@@ -234,11 +253,11 @@ function block_core_breadcrumbs_get_post_title( $post_id_or_object ) {
234
253
  /**
235
254
  * Generates breadcrumb items from hierarchical post type ancestors.
236
255
  *
237
- * @since 6.9.0
256
+ * @since 7.0.0
238
257
  *
239
258
  * @param int $post_id The post ID.
240
259
  *
241
- * @return array Array of breadcrumb HTML items.
260
+ * @return array Array of breadcrumb item data.
242
261
  */
243
262
  function block_core_breadcrumbs_get_hierarchical_post_type_breadcrumbs( $post_id ) {
244
263
  $breadcrumb_items = array();
@@ -246,10 +265,10 @@ function block_core_breadcrumbs_get_hierarchical_post_type_breadcrumbs( $post_id
246
265
  $ancestors = array_reverse( $ancestors );
247
266
 
248
267
  foreach ( $ancestors as $ancestor_id ) {
249
- $breadcrumb_items[] = block_core_breadcrumbs_create_link(
250
- get_permalink( $ancestor_id ),
251
- block_core_breadcrumbs_get_post_title( $ancestor_id ),
252
- true
268
+ $breadcrumb_items[] = array(
269
+ 'label' => block_core_breadcrumbs_get_post_title( $ancestor_id ),
270
+ 'url' => get_permalink( $ancestor_id ),
271
+ 'allow_html' => true,
253
272
  );
254
273
  }
255
274
  return $breadcrumb_items;
@@ -260,12 +279,12 @@ function block_core_breadcrumbs_get_hierarchical_post_type_breadcrumbs( $post_id
260
279
  *
261
280
  * For hierarchical taxonomies, retrieves and formats ancestor terms as breadcrumb links.
262
281
  *
263
- * @since 6.9.0
282
+ * @since 7.0.0
264
283
  *
265
284
  * @param int $term_id The term ID.
266
285
  * @param string $taxonomy The taxonomy name.
267
286
  *
268
- * @return array Array of breadcrumb HTML items for ancestors.
287
+ * @return array Array of breadcrumb item data for ancestors.
269
288
  */
270
289
  function block_core_breadcrumbs_get_term_ancestors_items( $term_id, $taxonomy ) {
271
290
  $breadcrumb_items = array();
@@ -277,9 +296,9 @@ function block_core_breadcrumbs_get_term_ancestors_items( $term_id, $taxonomy )
277
296
  foreach ( $term_ancestors as $ancestor_id ) {
278
297
  $ancestor_term = get_term( $ancestor_id, $taxonomy );
279
298
  if ( $ancestor_term && ! is_wp_error( $ancestor_term ) ) {
280
- $breadcrumb_items[] = block_core_breadcrumbs_create_link(
281
- get_term_link( $ancestor_term ),
282
- $ancestor_term->name
299
+ $breadcrumb_items[] = array(
300
+ 'label' => $ancestor_term->name,
301
+ 'url' => get_term_link( $ancestor_term ),
283
302
  );
284
303
  }
285
304
  }
@@ -294,9 +313,9 @@ function block_core_breadcrumbs_get_term_ancestors_items( $term_id, $taxonomy )
294
313
  * Handles taxonomy archives, post type archives, date archives, and author archives.
295
314
  * For hierarchical taxonomies, includes ancestor terms in the breadcrumb trail.
296
315
  *
297
- * @since 6.9.0
316
+ * @since 7.0.0
298
317
  *
299
- * @return array Array of breadcrumb HTML items.
318
+ * @return array Array of breadcrumb item data.
300
319
  */
301
320
  function block_core_breadcrumbs_get_archive_breadcrumbs() {
302
321
  $breadcrumb_items = array();
@@ -323,16 +342,16 @@ function block_core_breadcrumbs_get_archive_breadcrumbs() {
323
342
  if ( $year ) {
324
343
  if ( $month ) {
325
344
  // Year is linked if we have month.
326
- $breadcrumb_items[] = block_core_breadcrumbs_create_link(
327
- get_year_link( $year ),
328
- $year
345
+ $breadcrumb_items[] = array(
346
+ 'label' => $year,
347
+ 'url' => get_year_link( $year ),
329
348
  );
330
349
 
331
350
  if ( $day ) {
332
351
  // Month is linked if we have day.
333
- $breadcrumb_items[] = block_core_breadcrumbs_create_link(
334
- get_month_link( $year, $month ),
335
- date_i18n( 'F', mktime( 0, 0, 0, $month, 1, $year ) )
352
+ $breadcrumb_items[] = array(
353
+ 'label' => date_i18n( 'F', mktime( 0, 0, 0, $month, 1, $year ) ),
354
+ 'url' => get_month_link( $year, $month ),
336
355
  );
337
356
  // Add day (current if not paginated, link if paginated).
338
357
  $breadcrumb_items[] = block_core_breadcrumbs_create_item(
@@ -398,7 +417,7 @@ function block_core_breadcrumbs_get_archive_breadcrumbs() {
398
417
  if ( $post_type_object ) {
399
418
  // Add post type (current if not paginated, link if paginated).
400
419
  $breadcrumb_items[] = block_core_breadcrumbs_create_item(
401
- $post_type_object->labels->name,
420
+ $post_type_object->labels->archives,
402
421
  $is_paged
403
422
  );
404
423
  }
@@ -426,15 +445,16 @@ function block_core_breadcrumbs_get_archive_breadcrumbs() {
426
445
  * Finds the first publicly queryable taxonomy with terms assigned to the post
427
446
  * and generates breadcrumb links, including hierarchical term ancestors if applicable.
428
447
  *
429
- * @since 6.9.0
448
+ * @since 7.0.0
430
449
  *
431
450
  * @param int $post_id The post ID.
432
451
  * @param string $post_type The post type name.
433
452
  *
434
- * @return array Array of breadcrumb HTML items.
453
+ * @return array Array of breadcrumb item data.
435
454
  */
436
455
  function block_core_breadcrumbs_get_terms_breadcrumbs( $post_id, $post_type ) {
437
456
  $breadcrumb_items = array();
457
+
438
458
  // Get public taxonomies for this post type.
439
459
  $taxonomies = wp_filter_object_list(
440
460
  get_object_taxonomies( $post_type, 'objects' ),
@@ -445,32 +465,83 @@ function block_core_breadcrumbs_get_terms_breadcrumbs( $post_id, $post_type ) {
445
465
  );
446
466
 
447
467
  if ( empty( $taxonomies ) ) {
448
- return array();
468
+ return $breadcrumb_items;
449
469
  }
450
470
 
451
- // Find the first taxonomy that has terms assigned to this post.
471
+ /**
472
+ * Filters breadcrumb settings on a per-post-type basis.
473
+ *
474
+ * Allow developers to customize breadcrumb behavior for specific post types.
475
+ *
476
+ * @since 7.0.0
477
+ *
478
+ * @param array $settings {
479
+ * Array of breadcrumb settings. Default empty array.
480
+ *
481
+ * @type string $taxonomy Optional. Taxonomy slug to use for breadcrumbs.
482
+ * The taxonomy must be registered for the post type and have
483
+ * terms assigned to the post. If not found or has no terms,
484
+ * fall back to the first available taxonomy with terms.
485
+ * @type string $term Optional. Term slug to use when the post has multiple terms
486
+ * in the selected taxonomy. If the term is not found or not
487
+ * assigned to the post, fall back to the first term. If the
488
+ * post has only one term, that term is used regardless.
489
+ * }
490
+ * @param string $post_type The post type slug.
491
+ */
492
+ $settings = apply_filters( 'block_core_breadcrumbs_post_type_settings', array(), $post_type );
493
+
452
494
  $taxonomy_name = null;
453
495
  $terms = array();
454
- foreach ( $taxonomies as $taxonomy ) {
455
- $post_terms = get_the_terms( $post_id, $taxonomy->name );
456
- if ( ! empty( $post_terms ) && ! is_wp_error( $post_terms ) ) {
457
- $taxonomy_name = $taxonomy->name;
458
- $terms = $post_terms;
459
- break;
496
+
497
+ // Try preferred taxonomy first if specified.
498
+ if ( ! empty( $settings['taxonomy'] ) ) {
499
+ foreach ( $taxonomies as $taxonomy ) {
500
+ if ( $taxonomy->name === $settings['taxonomy'] ) {
501
+ $post_terms = get_the_terms( $post_id, $taxonomy->name );
502
+ if ( ! empty( $post_terms ) && ! is_wp_error( $post_terms ) ) {
503
+ $taxonomy_name = $taxonomy->name;
504
+ $terms = $post_terms;
505
+ }
506
+ break;
507
+ }
508
+ }
509
+ }
510
+
511
+ // If no preferred taxonomy or it didn't have terms, find the first taxonomy with terms.
512
+ if ( empty( $terms ) ) {
513
+ foreach ( $taxonomies as $taxonomy ) {
514
+ $post_terms = get_the_terms( $post_id, $taxonomy->name );
515
+ if ( ! empty( $post_terms ) && ! is_wp_error( $post_terms ) ) {
516
+ $taxonomy_name = $taxonomy->name;
517
+ $terms = $post_terms;
518
+ break;
519
+ }
460
520
  }
461
521
  }
462
522
 
463
523
  if ( ! empty( $terms ) ) {
464
- // Use the first term (if multiple are assigned).
524
+ // Select which term to use.
465
525
  $term = reset( $terms );
526
+
527
+ // Try preferred term if specified and post has multiple terms.
528
+ if ( ! empty( $settings['term'] ) && count( $terms ) > 1 ) {
529
+ foreach ( $terms as $candidate_term ) {
530
+ if ( $candidate_term->slug === $settings['term'] ) {
531
+ $term = $candidate_term;
532
+ break;
533
+ }
534
+ }
535
+ }
536
+
466
537
  // Add hierarchical term ancestors if applicable.
467
538
  $breadcrumb_items = array_merge(
468
539
  $breadcrumb_items,
469
540
  block_core_breadcrumbs_get_term_ancestors_items( $term->term_id, $taxonomy_name )
470
541
  );
471
- $breadcrumb_items[] = block_core_breadcrumbs_create_link(
472
- get_term_link( $term ),
473
- $term->name
542
+ $breadcrumb_items[] = array(
543
+ 'label' => $term->name,
544
+ 'url' => get_term_link( $term ),
474
545
  );
475
546
  }
476
547
  return $breadcrumb_items;
@@ -479,7 +550,7 @@ function block_core_breadcrumbs_get_terms_breadcrumbs( $post_id, $post_type ) {
479
550
  /**
480
551
  * Registers the `core/breadcrumbs` block on the server.
481
552
  *
482
- * @since 6.9.0
553
+ * @since 7.0.0
483
554
  */
484
555
  function register_block_core_breadcrumbs() {
485
556
  register_block_type_from_metadata(
@@ -3,6 +3,7 @@
3
3
  */
4
4
  import { __ } from '@wordpress/i18n';
5
5
  import { button as icon } from '@wordpress/icons';
6
+ import { privateApis as blocksPrivateApis } from '@wordpress/blocks';
6
7
 
7
8
  /**
8
9
  * Internal dependencies
@@ -12,6 +13,9 @@ import deprecated from './deprecated';
12
13
  import edit from './edit';
13
14
  import metadata from './block.json';
14
15
  import save from './save';
16
+ import { unlock } from '../lock-unlock';
17
+
18
+ const { fieldsKey, formKey } = unlock( blocksPrivateApis );
15
19
 
16
20
  const { name } = metadata;
17
21
 
@@ -34,4 +38,27 @@ export const settings = {
34
38
  } ),
35
39
  };
36
40
 
41
+ if ( window.__experimentalContentOnlyPatternInsertion ) {
42
+ settings[ fieldsKey ] = [
43
+ {
44
+ id: 'text',
45
+ label: __( 'Content' ),
46
+ type: 'richtext',
47
+ },
48
+ {
49
+ id: 'link',
50
+ label: __( 'Link' ),
51
+ type: 'link',
52
+ mapping: {
53
+ url: 'url',
54
+ rel: 'rel',
55
+ linkTarget: 'linkTarget',
56
+ },
57
+ },
58
+ ];
59
+ settings[ formKey ] = {
60
+ fields: [ 'text' ],
61
+ };
62
+ }
63
+
37
64
  export const init = () => initBlock( { name, metadata, settings } );
package/src/code/index.js CHANGED
@@ -3,6 +3,7 @@
3
3
  */
4
4
  import { __ } from '@wordpress/i18n';
5
5
  import { code as icon } from '@wordpress/icons';
6
+ import { privateApis as blocksPrivateApis } from '@wordpress/blocks';
6
7
 
7
8
  /**
8
9
  * Internal dependencies
@@ -12,6 +13,9 @@ import edit from './edit';
12
13
  import metadata from './block.json';
13
14
  import save from './save';
14
15
  import transforms from './transforms';
16
+ import { unlock } from '../lock-unlock';
17
+
18
+ const { fieldsKey, formKey } = unlock( blocksPrivateApis );
15
19
 
16
20
  const { name } = metadata;
17
21
 
@@ -39,4 +43,17 @@ export const settings = {
39
43
  save,
40
44
  };
41
45
 
46
+ if ( window.__experimentalContentOnlyPatternInsertion ) {
47
+ settings[ fieldsKey ] = [
48
+ {
49
+ id: 'content',
50
+ label: __( 'Code' ),
51
+ type: 'richtext',
52
+ },
53
+ ];
54
+ settings[ formKey ] = {
55
+ fields: [ 'content' ],
56
+ };
57
+ }
58
+
42
59
  export const init = () => initBlock( { name, metadata, settings } );
@@ -11,12 +11,15 @@ import {
11
11
  privateApis as blockEditorPrivateApis,
12
12
  } from '@wordpress/block-editor';
13
13
  import { __ } from '@wordpress/i18n';
14
+ import { MenuItem } from '@wordpress/components';
15
+ import { link } from '@wordpress/icons';
14
16
 
15
17
  /**
16
18
  * Internal dependencies
17
19
  */
18
20
  import { ALLOWED_MEDIA_TYPES } from '../shared';
19
21
  import { unlock } from '../../lock-unlock';
22
+ import EmbedVideoUrlInput from './embed-video-url-input';
20
23
 
21
24
  const { cleanEmptyObject } = unlock( blockEditorPrivateApis );
22
25
 
@@ -27,6 +30,7 @@ export default function CoverBlockControls( {
27
30
  currentSettings,
28
31
  toggleUseFeaturedImage,
29
32
  onClearMedia,
33
+ onSelectEmbedUrl,
30
34
  blockEditingMode,
31
35
  } ) {
32
36
  const { contentPosition, id, useFeaturedImage, minHeight, minHeightUnit } =
@@ -36,6 +40,7 @@ export default function CoverBlockControls( {
36
40
  const [ prevMinHeightValue, setPrevMinHeightValue ] = useState( minHeight );
37
41
  const [ prevMinHeightUnit, setPrevMinHeightUnit ] =
38
42
  useState( minHeightUnit );
43
+ const [ isEmbedUrlInputOpen, setIsEmbedUrlInputOpen ] = useState( false );
39
44
  const isMinFullHeight =
40
45
  minHeightUnit === 'vh' &&
41
46
  minHeight === 100 &&
@@ -102,14 +107,33 @@ export default function CoverBlockControls( {
102
107
  mediaId={ id }
103
108
  mediaURL={ url }
104
109
  allowedTypes={ ALLOWED_MEDIA_TYPES }
105
- accept="image/*,video/*"
106
110
  onSelect={ onSelectMedia }
107
111
  onToggleFeaturedImage={ toggleUseFeaturedImage }
108
112
  useFeaturedImage={ useFeaturedImage }
109
113
  name={ ! url ? __( 'Add media' ) : __( 'Replace' ) }
110
114
  onReset={ onClearMedia }
111
- />
115
+ >
116
+ { ( { onClose } ) => (
117
+ <MenuItem
118
+ icon={ link }
119
+ onClick={ () => {
120
+ setIsEmbedUrlInputOpen( true );
121
+ onClose();
122
+ } }
123
+ >
124
+ { __( 'Embed video from URL' ) }
125
+ </MenuItem>
126
+ ) }
127
+ </MediaReplaceFlow>
112
128
  </BlockControls>
129
+ { isEmbedUrlInputOpen && (
130
+ <EmbedVideoUrlInput
131
+ onSubmit={ ( embedUrl ) => {
132
+ onSelectEmbedUrl( embedUrl );
133
+ } }
134
+ onClose={ () => setIsEmbedUrlInputOpen( false ) }
135
+ />
136
+ ) }
113
137
  </>
114
138
  );
115
139
  }
@@ -25,7 +25,6 @@ export default function CoverPlaceholder( {
25
25
  title: __( 'Cover' ),
26
26
  } }
27
27
  onSelect={ onSelectMedia }
28
- accept="image/*,video/*"
29
28
  allowedTypes={ ALLOWED_MEDIA_TYPES }
30
29
  disableMediaButtons={ disableMediaButtons }
31
30
  onToggleFeaturedImage={ toggleUseFeaturedImage }
@@ -0,0 +1,74 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { useState } from '@wordpress/element';
5
+ import {
6
+ __experimentalConfirmDialog as ConfirmDialog,
7
+ __experimentalVStack as VStack,
8
+ TextControl,
9
+ Notice,
10
+ } from '@wordpress/components';
11
+ import { __ } from '@wordpress/i18n';
12
+
13
+ /**
14
+ * Internal dependencies
15
+ */
16
+ import { isValidVideoEmbedUrl } from '../embed-video-utils';
17
+
18
+ export default function EmbedVideoUrlInput( { onSubmit, onClose } ) {
19
+ const [ url, setUrl ] = useState( '' );
20
+ const [ error, setError ] = useState( '' );
21
+
22
+ const handleConfirm = () => {
23
+ if ( ! url ) {
24
+ setError( __( 'Please enter a URL.' ) );
25
+ return;
26
+ }
27
+
28
+ if ( ! isValidVideoEmbedUrl( url ) ) {
29
+ setError(
30
+ __(
31
+ 'This URL is not supported. Please enter a valid video link from a supported provider.'
32
+ )
33
+ );
34
+ return;
35
+ }
36
+
37
+ onSubmit( url );
38
+ onClose();
39
+ };
40
+
41
+ return (
42
+ <ConfirmDialog
43
+ isOpen
44
+ onConfirm={ handleConfirm }
45
+ onCancel={ onClose }
46
+ confirmButtonText={ __( 'Add video' ) }
47
+ size="medium"
48
+ >
49
+ <VStack spacing={ 4 }>
50
+ { error && (
51
+ <Notice status="error" isDismissible={ false }>
52
+ { error }
53
+ </Notice>
54
+ ) }
55
+ <TextControl
56
+ __next40pxDefaultSize
57
+ label={ __( 'Video URL' ) }
58
+ value={ url }
59
+ onChange={ ( value ) => {
60
+ setUrl( value );
61
+ setError( '' );
62
+ } }
63
+ placeholder={ __(
64
+ 'Enter YouTube, Vimeo, or other video URL'
65
+ ) }
66
+ __nextHasNoMarginBottom
67
+ help={ __(
68
+ 'Add a background video to the cover block that will autoplay in a loop.'
69
+ ) }
70
+ />
71
+ </VStack>
72
+ </ConfirmDialog>
73
+ );
74
+ }