@wordpress/block-library 8.14.0 → 8.16.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 (365) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/build/avatar/edit.js +1 -0
  3. package/build/avatar/edit.js.map +1 -1
  4. package/build/avatar/index.js +3 -0
  5. package/build/avatar/index.js.map +1 -1
  6. package/build/block/edit.js +2 -30
  7. package/build/block/edit.js.map +1 -1
  8. package/build/block/index.js +2 -1
  9. package/build/block/index.js.map +1 -1
  10. package/build/buttons/edit.js +2 -2
  11. package/build/buttons/edit.js.map +1 -1
  12. package/build/column/edit.native.js +1 -4
  13. package/build/column/edit.native.js.map +1 -1
  14. package/build/columns/edit.js +1 -0
  15. package/build/columns/edit.js.map +1 -1
  16. package/build/comment-author-avatar/edit.js +1 -0
  17. package/build/comment-author-avatar/edit.js.map +1 -1
  18. package/build/cover/deprecated.js +4 -2
  19. package/build/cover/deprecated.js.map +1 -1
  20. package/build/cover/index.js +2 -1
  21. package/build/cover/index.js.map +1 -1
  22. package/build/embed/embed-placeholder.native.js +37 -13
  23. package/build/embed/embed-placeholder.native.js.map +1 -1
  24. package/build/file/index.js +1 -2
  25. package/build/file/index.js.map +1 -1
  26. package/build/file/inspector.js +1 -0
  27. package/build/file/inspector.js.map +1 -1
  28. package/build/file/view-interactivity.js +23 -0
  29. package/build/file/view-interactivity.js.map +1 -0
  30. package/build/file/view.js +1 -15
  31. package/build/file/view.js.map +1 -1
  32. package/build/footnotes/edit.js +31 -1
  33. package/build/footnotes/edit.js.map +1 -1
  34. package/build/footnotes/format.js +119 -23
  35. package/build/footnotes/format.js.map +1 -1
  36. package/build/footnotes/index.js +45 -4
  37. package/build/footnotes/index.js.map +1 -1
  38. package/build/gallery/edit.js +8 -6
  39. package/build/gallery/edit.js.map +1 -1
  40. package/build/image/deprecated.js +106 -2
  41. package/build/image/deprecated.js.map +1 -1
  42. package/build/image/image.js +2 -2
  43. package/build/image/image.js.map +1 -1
  44. package/build/image/index.js +2 -1
  45. package/build/image/index.js.map +1 -1
  46. package/build/index.js +3 -1
  47. package/build/index.js.map +1 -1
  48. package/build/latest-comments/edit.js +1 -0
  49. package/build/latest-comments/edit.js.map +1 -1
  50. package/build/latest-posts/edit.js +2 -0
  51. package/build/latest-posts/edit.js.map +1 -1
  52. package/build/list/edit.js +4 -4
  53. package/build/list/edit.js.map +1 -1
  54. package/build/list-item/hooks/use-merge.js +10 -1
  55. package/build/list-item/hooks/use-merge.js.map +1 -1
  56. package/build/media-text/media-container.native.js +2 -1
  57. package/build/media-text/media-container.native.js.map +1 -1
  58. package/build/missing/edit.native.js +7 -5
  59. package/build/missing/edit.native.js.map +1 -1
  60. package/build/navigation/constants.js +10 -4
  61. package/build/navigation/constants.js.map +1 -1
  62. package/build/navigation/edit/index.js +16 -2
  63. package/build/navigation/edit/index.js.map +1 -1
  64. package/build/navigation/edit/inner-blocks.js +2 -2
  65. package/build/navigation/edit/inner-blocks.js.map +1 -1
  66. package/build/navigation/edit/menu-inspector-controls.js +1 -1
  67. package/build/navigation/edit/menu-inspector-controls.js.map +1 -1
  68. package/build/navigation/edit/navigation-menu-selector.js +4 -4
  69. package/build/navigation/edit/navigation-menu-selector.js.map +1 -1
  70. package/build/navigation/edit/unsaved-inner-blocks.js +2 -2
  71. package/build/navigation/edit/unsaved-inner-blocks.js.map +1 -1
  72. package/build/navigation/edit/use-convert-classic-menu-to-block-menu.js +10 -15
  73. package/build/navigation/edit/use-convert-classic-menu-to-block-menu.js.map +1 -1
  74. package/build/navigation/index.js +2 -3
  75. package/build/navigation/index.js.map +1 -1
  76. package/build/navigation/use-navigation-menu.js +33 -45
  77. package/build/navigation/use-navigation-menu.js.map +1 -1
  78. package/build/navigation/view-interactivity.js +185 -0
  79. package/build/navigation/view-interactivity.js.map +1 -0
  80. package/build/navigation/view-modal.js +125 -0
  81. package/build/navigation/view-modal.js.map +1 -0
  82. package/build/navigation/view.js +71 -163
  83. package/build/navigation/view.js.map +1 -1
  84. package/build/navigation-link/edit.js +12 -7
  85. package/build/navigation-link/edit.js.map +1 -1
  86. package/build/navigation-submenu/edit.js +2 -2
  87. package/build/navigation-submenu/edit.js.map +1 -1
  88. package/build/pattern/edit.js +28 -4
  89. package/build/pattern/edit.js.map +1 -1
  90. package/build/preformatted/index.js +4 -0
  91. package/build/preformatted/index.js.map +1 -1
  92. package/build/query-pagination/edit.js +1 -1
  93. package/build/query-pagination/edit.js.map +1 -1
  94. package/build/query-title/edit.js +43 -1
  95. package/build/query-title/edit.js.map +1 -1
  96. package/build/quote/transforms.js +8 -0
  97. package/build/quote/transforms.js.map +1 -1
  98. package/build/rss/edit.js +3 -0
  99. package/build/rss/edit.js.map +1 -1
  100. package/build/search/edit.js +4 -3
  101. package/build/search/edit.js.map +1 -1
  102. package/build/search/index.js +1 -0
  103. package/build/search/index.js.map +1 -1
  104. package/build/search/view.js +166 -62
  105. package/build/search/view.js.map +1 -1
  106. package/build/site-logo/edit.js +1 -0
  107. package/build/site-logo/edit.js.map +1 -1
  108. package/build/social-link/icons/index.js +13 -0
  109. package/build/social-link/icons/index.js.map +1 -1
  110. package/build/social-link/icons/threads.js +25 -0
  111. package/build/social-link/icons/threads.js.map +1 -0
  112. package/build/social-link/variations.js +7 -0
  113. package/build/social-link/variations.js.map +1 -1
  114. package/build/tag-cloud/edit.js +1 -0
  115. package/build/tag-cloud/edit.js.map +1 -1
  116. package/build/template-part/edit/import-controls.js +1 -1
  117. package/build/template-part/edit/import-controls.js.map +1 -1
  118. package/build/template-part/edit/index.js +1 -1
  119. package/build/template-part/edit/index.js.map +1 -1
  120. package/build/text-columns/edit.js +1 -0
  121. package/build/text-columns/edit.js.map +1 -1
  122. package/build-module/avatar/edit.js +1 -0
  123. package/build-module/avatar/edit.js.map +1 -1
  124. package/build-module/avatar/index.js +3 -0
  125. package/build-module/avatar/index.js.map +1 -1
  126. package/build-module/block/edit.js +4 -29
  127. package/build-module/block/edit.js.map +1 -1
  128. package/build-module/block/index.js +2 -1
  129. package/build-module/block/index.js.map +1 -1
  130. package/build-module/buttons/edit.js +2 -2
  131. package/build-module/buttons/edit.js.map +1 -1
  132. package/build-module/column/edit.native.js +1 -4
  133. package/build-module/column/edit.native.js.map +1 -1
  134. package/build-module/columns/edit.js +1 -0
  135. package/build-module/columns/edit.js.map +1 -1
  136. package/build-module/comment-author-avatar/edit.js +1 -0
  137. package/build-module/comment-author-avatar/edit.js.map +1 -1
  138. package/build-module/cover/deprecated.js +4 -2
  139. package/build-module/cover/deprecated.js.map +1 -1
  140. package/build-module/cover/index.js +2 -1
  141. package/build-module/cover/index.js.map +1 -1
  142. package/build-module/embed/embed-placeholder.native.js +37 -14
  143. package/build-module/embed/embed-placeholder.native.js.map +1 -1
  144. package/build-module/file/index.js +1 -2
  145. package/build-module/file/index.js.map +1 -1
  146. package/build-module/file/inspector.js +1 -0
  147. package/build-module/file/inspector.js.map +1 -1
  148. package/build-module/file/view-interactivity.js +19 -0
  149. package/build-module/file/view-interactivity.js.map +1 -0
  150. package/build-module/file/view.js +2 -15
  151. package/build-module/file/view.js.map +1 -1
  152. package/build-module/footnotes/edit.js +29 -2
  153. package/build-module/footnotes/edit.js.map +1 -1
  154. package/build-module/footnotes/format.js +120 -25
  155. package/build-module/footnotes/format.js.map +1 -1
  156. package/build-module/footnotes/index.js +45 -4
  157. package/build-module/footnotes/index.js.map +1 -1
  158. package/build-module/gallery/edit.js +8 -6
  159. package/build-module/gallery/edit.js.map +1 -1
  160. package/build-module/image/deprecated.js +107 -3
  161. package/build-module/image/deprecated.js.map +1 -1
  162. package/build-module/image/image.js +2 -2
  163. package/build-module/image/image.js.map +1 -1
  164. package/build-module/image/index.js +2 -1
  165. package/build-module/image/index.js.map +1 -1
  166. package/build-module/index.js +3 -1
  167. package/build-module/index.js.map +1 -1
  168. package/build-module/latest-comments/edit.js +1 -0
  169. package/build-module/latest-comments/edit.js.map +1 -1
  170. package/build-module/latest-posts/edit.js +2 -0
  171. package/build-module/latest-posts/edit.js.map +1 -1
  172. package/build-module/list/edit.js +4 -4
  173. package/build-module/list/edit.js.map +1 -1
  174. package/build-module/list-item/hooks/use-merge.js +10 -1
  175. package/build-module/list-item/hooks/use-merge.js.map +1 -1
  176. package/build-module/media-text/media-container.native.js +2 -1
  177. package/build-module/media-text/media-container.native.js.map +1 -1
  178. package/build-module/missing/edit.native.js +8 -6
  179. package/build-module/missing/edit.native.js.map +1 -1
  180. package/build-module/navigation/constants.js +8 -3
  181. package/build-module/navigation/constants.js.map +1 -1
  182. package/build-module/navigation/edit/index.js +17 -3
  183. package/build-module/navigation/edit/index.js.map +1 -1
  184. package/build-module/navigation/edit/inner-blocks.js +2 -2
  185. package/build-module/navigation/edit/inner-blocks.js.map +1 -1
  186. package/build-module/navigation/edit/menu-inspector-controls.js +1 -1
  187. package/build-module/navigation/edit/menu-inspector-controls.js.map +1 -1
  188. package/build-module/navigation/edit/navigation-menu-selector.js +4 -4
  189. package/build-module/navigation/edit/navigation-menu-selector.js.map +1 -1
  190. package/build-module/navigation/edit/unsaved-inner-blocks.js +2 -2
  191. package/build-module/navigation/edit/unsaved-inner-blocks.js.map +1 -1
  192. package/build-module/navigation/edit/use-convert-classic-menu-to-block-menu.js +10 -14
  193. package/build-module/navigation/edit/use-convert-classic-menu-to-block-menu.js.map +1 -1
  194. package/build-module/navigation/index.js +2 -3
  195. package/build-module/navigation/index.js.map +1 -1
  196. package/build-module/navigation/use-navigation-menu.js +35 -47
  197. package/build-module/navigation/use-navigation-menu.js.map +1 -1
  198. package/build-module/navigation/view-interactivity.js +182 -0
  199. package/build-module/navigation/view-interactivity.js.map +1 -0
  200. package/build-module/navigation/view-modal.js +120 -0
  201. package/build-module/navigation/view-modal.js.map +1 -0
  202. package/build-module/navigation/view.js +72 -163
  203. package/build-module/navigation/view.js.map +1 -1
  204. package/build-module/navigation-link/edit.js +12 -7
  205. package/build-module/navigation-link/edit.js.map +1 -1
  206. package/build-module/navigation-submenu/edit.js +2 -2
  207. package/build-module/navigation-submenu/edit.js.map +1 -1
  208. package/build-module/pattern/edit.js +27 -4
  209. package/build-module/pattern/edit.js.map +1 -1
  210. package/build-module/preformatted/index.js +4 -0
  211. package/build-module/preformatted/index.js.map +1 -1
  212. package/build-module/query-pagination/edit.js +1 -1
  213. package/build-module/query-pagination/edit.js.map +1 -1
  214. package/build-module/query-title/edit.js +44 -3
  215. package/build-module/query-title/edit.js.map +1 -1
  216. package/build-module/quote/transforms.js +8 -0
  217. package/build-module/quote/transforms.js.map +1 -1
  218. package/build-module/rss/edit.js +3 -0
  219. package/build-module/rss/edit.js.map +1 -1
  220. package/build-module/search/edit.js +4 -3
  221. package/build-module/search/edit.js.map +1 -1
  222. package/build-module/search/index.js +1 -0
  223. package/build-module/search/index.js.map +1 -1
  224. package/build-module/search/view.js +166 -62
  225. package/build-module/search/view.js.map +1 -1
  226. package/build-module/site-logo/edit.js +1 -0
  227. package/build-module/site-logo/edit.js.map +1 -1
  228. package/build-module/social-link/icons/index.js +1 -0
  229. package/build-module/social-link/icons/index.js.map +1 -1
  230. package/build-module/social-link/icons/threads.js +15 -0
  231. package/build-module/social-link/icons/threads.js.map +1 -0
  232. package/build-module/social-link/variations.js +8 -1
  233. package/build-module/social-link/variations.js.map +1 -1
  234. package/build-module/tag-cloud/edit.js +1 -0
  235. package/build-module/tag-cloud/edit.js.map +1 -1
  236. package/build-module/template-part/edit/import-controls.js +2 -2
  237. package/build-module/template-part/edit/import-controls.js.map +1 -1
  238. package/build-module/template-part/edit/index.js +1 -1
  239. package/build-module/template-part/edit/index.js.map +1 -1
  240. package/build-module/text-columns/edit.js +1 -0
  241. package/build-module/text-columns/edit.js.map +1 -1
  242. package/build-style/details/style-rtl.css +4 -2
  243. package/build-style/details/style.css +4 -2
  244. package/build-style/footnotes/style-rtl.css +4 -3
  245. package/build-style/footnotes/style.css +4 -3
  246. package/build-style/navigation/style-rtl.css +14 -2
  247. package/build-style/navigation/style.css +14 -2
  248. package/build-style/preformatted/style-rtl.css +2 -1
  249. package/build-style/preformatted/style.css +2 -1
  250. package/build-style/query-pagination/style-rtl.css +4 -2
  251. package/build-style/query-pagination/style.css +4 -2
  252. package/build-style/social-links/style-rtl.css +7 -0
  253. package/build-style/social-links/style.css +7 -0
  254. package/build-style/style-rtl.css +36 -10
  255. package/build-style/style.css +36 -10
  256. package/build-style/video/style-rtl.css +1 -0
  257. package/build-style/video/style.css +1 -0
  258. package/package.json +33 -32
  259. package/src/audio/test/__snapshots__/edit.native.js.snap +118 -33
  260. package/src/avatar/block.json +3 -0
  261. package/src/avatar/edit.js +1 -0
  262. package/src/block/block.json +2 -1
  263. package/src/block/edit.js +1 -39
  264. package/src/block/editor.native.scss +2 -2
  265. package/src/buttons/edit.js +2 -2
  266. package/src/buttons/test/edit.native.js +4 -0
  267. package/src/column/edit.native.js +4 -10
  268. package/src/column/editor.native.scss +0 -4
  269. package/src/columns/edit.js +1 -0
  270. package/src/columns/test/edit.native.js +5 -0
  271. package/src/comment-author-avatar/edit.js +1 -0
  272. package/src/comment-template/index.php +7 -2
  273. package/src/cover/block.json +2 -1
  274. package/src/cover/deprecated.js +2 -0
  275. package/src/cover/test/edit.native.js +8 -0
  276. package/src/embed/embed-placeholder.native.js +80 -47
  277. package/src/embed/styles.native.scss +54 -18
  278. package/src/embed/test/index.native.js +13 -5
  279. package/src/file/block.json +1 -2
  280. package/src/file/index.php +20 -2
  281. package/src/file/inspector.js +1 -0
  282. package/src/file/test/__snapshots__/edit.native.js.snap +119 -33
  283. package/src/file/view-interactivity.js +18 -0
  284. package/src/file/view.js +5 -14
  285. package/src/footnotes/block.json +44 -2
  286. package/src/footnotes/edit.js +33 -2
  287. package/src/footnotes/format.js +90 -25
  288. package/src/footnotes/index.js +0 -1
  289. package/src/footnotes/index.php +207 -0
  290. package/src/footnotes/style.scss +6 -3
  291. package/src/gallery/edit.js +42 -38
  292. package/src/gallery/test/index.native.js +31 -18
  293. package/src/heading/test/index.native.js +4 -0
  294. package/src/home-link/index.php +15 -2
  295. package/src/image/block.json +2 -1
  296. package/src/image/deprecated.js +109 -3
  297. package/src/image/image.js +2 -2
  298. package/src/image/index.php +45 -8
  299. package/src/image/test/edit.native.js +1 -2
  300. package/src/index.js +5 -1
  301. package/src/latest-comments/edit.js +1 -0
  302. package/src/latest-posts/edit.js +2 -0
  303. package/src/list/edit.js +6 -4
  304. package/src/list/test/edit.native.js +134 -33
  305. package/src/list-item/hooks/use-merge.js +12 -5
  306. package/src/media-text/media-container.native.js +1 -0
  307. package/src/missing/edit.native.js +12 -10
  308. package/src/missing/style.native.scss +19 -12
  309. package/src/missing/test/__snapshots__/edit.native.js.snap +42 -13
  310. package/src/navigation/block.json +2 -3
  311. package/src/navigation/constants.js +12 -6
  312. package/src/navigation/edit/index.js +29 -1
  313. package/src/navigation/edit/inner-blocks.js +2 -2
  314. package/src/navigation/edit/menu-inspector-controls.js +1 -1
  315. package/src/navigation/edit/navigation-menu-selector.js +8 -4
  316. package/src/navigation/edit/unsaved-inner-blocks.js +2 -2
  317. package/src/navigation/edit/use-convert-classic-menu-to-block-menu.js +17 -21
  318. package/src/navigation/index.php +50 -18
  319. package/src/navigation/style.scss +27 -8
  320. package/src/navigation/use-navigation-menu.js +39 -63
  321. package/src/navigation/view-interactivity.js +196 -0
  322. package/src/navigation/view-modal.js +127 -0
  323. package/src/navigation/view.js +96 -185
  324. package/src/navigation-link/edit.js +61 -47
  325. package/src/navigation-submenu/edit.js +2 -2
  326. package/src/paragraph/test/__snapshots__/edit.native.js.snap +1 -0
  327. package/src/paragraph/test/edit.native.js +81 -35
  328. package/src/pattern/edit.js +21 -0
  329. package/src/pattern/index.php +13 -1
  330. package/src/post-template/index.php +6 -2
  331. package/src/post-title/index.php +8 -3
  332. package/src/preformatted/block.json +4 -0
  333. package/src/preformatted/style.scss +4 -1
  334. package/src/preformatted/test/__snapshots__/edit.native.js.snap +2 -0
  335. package/src/pullquote/test/edit.native.js +12 -4
  336. package/src/query-pagination/edit.js +17 -14
  337. package/src/query-title/edit.js +48 -6
  338. package/src/quote/test/__snapshots__/transforms.native.js.snap +10 -0
  339. package/src/quote/test/edit.native.js +12 -4
  340. package/src/quote/test/transforms.native.js +5 -1
  341. package/src/quote/transforms.js +13 -0
  342. package/src/rss/edit.js +3 -0
  343. package/src/search/block.json +1 -0
  344. package/src/search/edit.js +4 -3
  345. package/src/search/index.php +26 -4
  346. package/src/search/test/__snapshots__/edit.native.js.snap +70 -0
  347. package/src/search/view.js +171 -67
  348. package/src/site-logo/edit.js +1 -0
  349. package/src/social-link/icons/index.js +1 -0
  350. package/src/social-link/icons/threads.js +10 -0
  351. package/src/social-link/index.php +4 -0
  352. package/src/social-link/socials-with-bg.scss +5 -0
  353. package/src/social-link/socials-without-bg.scss +4 -0
  354. package/src/social-link/variations.js +7 -0
  355. package/src/tag-cloud/edit.js +1 -0
  356. package/src/template-part/edit/import-controls.js +2 -2
  357. package/src/template-part/edit/index.js +1 -1
  358. package/src/template-part/index.php +7 -16
  359. package/src/text-columns/edit.js +1 -0
  360. package/src/video/style.scss +1 -0
  361. package/build/gallery/shared-icon.native.js +0 -38
  362. package/build/gallery/shared-icon.native.js.map +0 -1
  363. package/build-module/gallery/shared-icon.native.js +0 -24
  364. package/build-module/gallery/shared-icon.native.js.map +0 -1
  365. package/src/gallery/shared-icon.native.js +0 -23
@@ -9,10 +9,52 @@
9
9
  "textdomain": "default",
10
10
  "usesContext": [ "postId", "postType" ],
11
11
  "supports": {
12
+ "__experimentalBorder": {
13
+ "radius": true,
14
+ "color": true,
15
+ "width": true,
16
+ "style": true,
17
+ "__experimentalDefaultControls": {
18
+ "radius": false,
19
+ "color": false,
20
+ "width": false,
21
+ "style": false
22
+ }
23
+ },
24
+ "color": {
25
+ "background": true,
26
+ "link": true,
27
+ "text": true,
28
+ "__experimentalDefaultControls": {
29
+ "link": true,
30
+ "text": true
31
+ }
32
+ },
12
33
  "html": false,
13
34
  "multiple": false,
14
- "inserter": false,
15
- "reusable": false
35
+ "reusable": false,
36
+ "spacing": {
37
+ "margin": true,
38
+ "padding": true,
39
+ "__experimentalDefaultControls": {
40
+ "margin": false,
41
+ "padding": false
42
+ }
43
+ },
44
+ "typography": {
45
+ "fontSize": true,
46
+ "lineHeight": true,
47
+ "__experimentalFontFamily": true,
48
+ "__experimentalTextDecoration": true,
49
+ "__experimentalFontStyle": true,
50
+ "__experimentalFontWeight": true,
51
+ "__experimentalLetterSpacing": true,
52
+ "__experimentalTextTransform": true,
53
+ "__experimentalWritingMode": true,
54
+ "__experimentalDefaultControls": {
55
+ "fontSize": true
56
+ }
57
+ }
16
58
  },
17
59
  "style": "wp-block-footnotes"
18
60
  }
@@ -1,8 +1,11 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { RichText, useBlockProps } from '@wordpress/block-editor';
4
+ import { BlockIcon, RichText, useBlockProps } from '@wordpress/block-editor';
5
5
  import { useEntityProp } from '@wordpress/core-data';
6
+ import { __ } from '@wordpress/i18n';
7
+ import { Placeholder } from '@wordpress/components';
8
+ import { formatListNumbered as icon } from '@wordpress/icons';
6
9
 
7
10
  export default function FootnotesEdit( { context: { postType, postId } } ) {
8
11
  const [ meta, updateMeta ] = useEntityProp(
@@ -12,8 +15,36 @@ export default function FootnotesEdit( { context: { postType, postId } } ) {
12
15
  postId
13
16
  );
14
17
  const footnotes = meta?.footnotes ? JSON.parse( meta.footnotes ) : [];
18
+ const blockProps = useBlockProps();
19
+
20
+ if ( postType !== 'post' && postType !== 'page' ) {
21
+ return (
22
+ <div { ...blockProps }>
23
+ <Placeholder
24
+ icon={ <BlockIcon icon={ icon } /> }
25
+ label={ __( 'Footnotes' ) }
26
+ // To do: add instructions. We can't add new string in RC.
27
+ />
28
+ </div>
29
+ );
30
+ }
31
+
32
+ if ( ! footnotes.length ) {
33
+ return (
34
+ <div { ...blockProps }>
35
+ <Placeholder
36
+ icon={ <BlockIcon icon={ icon } /> }
37
+ label={ __( 'Footnotes' ) }
38
+ instructions={ __(
39
+ 'Footnotes found in blocks within this document will be displayed here.'
40
+ ) }
41
+ />
42
+ </div>
43
+ );
44
+ }
45
+
15
46
  return (
16
- <ol { ...useBlockProps() }>
47
+ <ol { ...blockProps }>
17
48
  { footnotes.map( ( { id, content } ) => (
18
49
  <li key={ id }>
19
50
  <RichText
@@ -12,61 +12,127 @@ import { insertObject } from '@wordpress/rich-text';
12
12
  import {
13
13
  RichTextToolbarButton,
14
14
  store as blockEditorStore,
15
+ privateApis,
15
16
  } from '@wordpress/block-editor';
16
17
  import { useSelect, useDispatch, useRegistry } from '@wordpress/data';
17
- import { createBlock } from '@wordpress/blocks';
18
+ import { createBlock, store as blocksStore } from '@wordpress/blocks';
18
19
 
19
20
  /**
20
21
  * Internal dependencies
21
22
  */
22
23
  import { name } from './block.json';
24
+ import { unlock } from '../lock-unlock';
25
+
26
+ const { usesContextKey } = unlock( privateApis );
23
27
 
24
28
  export const formatName = 'core/footnote';
29
+
30
+ const POST_CONTENT_BLOCK_NAME = 'core/post-content';
31
+ const SYNCED_PATTERN_BLOCK_NAME = 'core/block';
32
+
25
33
  export const format = {
26
34
  title: __( 'Footnote' ),
27
- tagName: 'a',
35
+ tagName: 'sup',
28
36
  className: 'fn',
29
37
  attributes: {
30
- id: 'id',
31
- href: 'href',
32
38
  'data-fn': 'data-fn',
33
39
  },
34
40
  contentEditable: false,
35
- edit: function Edit( { value, onChange, isObjectActive } ) {
41
+ [ usesContextKey ]: [ 'postType' ],
42
+ edit: function Edit( {
43
+ value,
44
+ onChange,
45
+ isObjectActive,
46
+ context: { postType },
47
+ } ) {
36
48
  const registry = useRegistry();
37
49
  const {
38
50
  getSelectedBlockClientId,
51
+ getBlocks,
39
52
  getBlockRootClientId,
40
53
  getBlockName,
41
- getBlocks,
54
+ getBlockParentsByBlockName,
42
55
  } = useSelect( blockEditorStore );
56
+ const footnotesBlockType = useSelect( ( select ) =>
57
+ select( blocksStore ).getBlockType( name )
58
+ );
59
+ /*
60
+ * This useSelect exists because we need to use its return value
61
+ * outside the event callback.
62
+ */
63
+ const isBlockWithinPattern = useSelect( ( select ) => {
64
+ const {
65
+ getBlockParentsByBlockName: _getBlockParentsByBlockName,
66
+ getSelectedBlockClientId: _getSelectedBlockClientId,
67
+ } = select( blockEditorStore );
68
+ const parentCoreBlocks = _getBlockParentsByBlockName(
69
+ _getSelectedBlockClientId(),
70
+ SYNCED_PATTERN_BLOCK_NAME
71
+ );
72
+ return parentCoreBlocks && parentCoreBlocks.length > 0;
73
+ }, [] );
74
+
43
75
  const { selectionChange, insertBlock } =
44
76
  useDispatch( blockEditorStore );
77
+
78
+ if ( ! footnotesBlockType ) {
79
+ return null;
80
+ }
81
+
82
+ if ( postType !== 'post' && postType !== 'page' ) {
83
+ return null;
84
+ }
85
+
86
+ // Checks if the selected block lives within a pattern.
87
+ if ( isBlockWithinPattern ) {
88
+ return null;
89
+ }
90
+
45
91
  function onClick() {
46
92
  registry.batch( () => {
47
- const id = createId();
48
- const newValue = insertObject(
49
- value,
50
- {
51
- type: formatName,
52
- attributes: {
53
- href: '#' + id,
54
- id: `${ id }-link`,
55
- 'data-fn': id,
93
+ let id;
94
+ if ( isObjectActive ) {
95
+ const object = value.replacements[ value.start ];
96
+ id = object?.attributes?.[ 'data-fn' ];
97
+ } else {
98
+ id = createId();
99
+ const newValue = insertObject(
100
+ value,
101
+ {
102
+ type: formatName,
103
+ attributes: {
104
+ 'data-fn': id,
105
+ },
106
+ innerHTML: `<a href="#${ id }" id="${ id }-link">*</a>`,
56
107
  },
57
- innerHTML: '*',
58
- },
59
- value.end,
60
- value.end
108
+ value.end,
109
+ value.end
110
+ );
111
+ newValue.start = newValue.end - 1;
112
+ onChange( newValue );
113
+ }
114
+
115
+ const selectedClientId = getSelectedBlockClientId();
116
+
117
+ /*
118
+ * Attempts to find a common parent post content block.
119
+ * This allows for locating blocks within a page edited in the site editor.
120
+ */
121
+ const parentPostContent = getBlockParentsByBlockName(
122
+ selectedClientId,
123
+ POST_CONTENT_BLOCK_NAME
61
124
  );
62
- newValue.start = newValue.end - 1;
63
125
 
64
- onChange( newValue );
126
+ // When called with a post content block, getBlocks will return
127
+ // the block with controlled inner blocks included.
128
+ const blocks = parentPostContent.length
129
+ ? getBlocks( parentPostContent[ 0 ] )
130
+ : getBlocks();
65
131
 
66
132
  // BFS search to find the first footnote block.
67
133
  let fnBlock = null;
68
134
  {
69
- const queue = [ ...getBlocks() ];
135
+ const queue = [ ...blocks ];
70
136
  while ( queue.length ) {
71
137
  const block = queue.shift();
72
138
  if ( block.name === name ) {
@@ -81,12 +147,11 @@ export const format = {
81
147
  // When there is no footnotes block in the post, create one and
82
148
  // insert it at the bottom.
83
149
  if ( ! fnBlock ) {
84
- const clientId = getSelectedBlockClientId();
85
- let rootClientId = getBlockRootClientId( clientId );
150
+ let rootClientId = getBlockRootClientId( selectedClientId );
86
151
 
87
152
  while (
88
153
  rootClientId &&
89
- getBlockName( rootClientId ) !== 'core/post-content'
154
+ getBlockName( rootClientId ) !== POST_CONTENT_BLOCK_NAME
90
155
  ) {
91
156
  rootClientId = getBlockRootClientId( rootClientId );
92
157
  }
@@ -21,7 +21,6 @@ export const settings = {
21
21
  edit,
22
22
  };
23
23
 
24
- // Would be good to remove the format and HoR if the block is unregistered.
25
24
  registerFormatType( formatName, format );
26
25
 
27
26
  export const init = () => {
@@ -8,6 +8,8 @@
8
8
  /**
9
9
  * Renders the `core/footnotes` block on the server.
10
10
  *
11
+ * @since 6.3.0
12
+ *
11
13
  * @param array $attributes Block attributes.
12
14
  * @param string $content Block default content.
13
15
  * @param WP_Block $block Block instance.
@@ -57,6 +59,8 @@ function render_block_core_footnotes( $attributes, $content, $block ) {
57
59
 
58
60
  /**
59
61
  * Registers the `core/footnotes` block on the server.
62
+ *
63
+ * @since 6.3.0
60
64
  */
61
65
  function register_block_core_footnotes() {
62
66
  foreach ( array( 'post', 'page' ) as $post_type ) {
@@ -78,3 +82,206 @@ function register_block_core_footnotes() {
78
82
  );
79
83
  }
80
84
  add_action( 'init', 'register_block_core_footnotes' );
85
+
86
+ /**
87
+ * Saves the footnotes meta value to the revision.
88
+ *
89
+ * @since 6.3.0
90
+ *
91
+ * @param int $revision_id The revision ID.
92
+ */
93
+ function wp_save_footnotes_meta( $revision_id ) {
94
+ $post_id = wp_is_post_revision( $revision_id );
95
+
96
+ if ( $post_id ) {
97
+ $footnotes = get_post_meta( $post_id, 'footnotes', true );
98
+
99
+ if ( $footnotes ) {
100
+ // Can't use update_post_meta() because it doesn't allow revisions.
101
+ update_metadata( 'post', $revision_id, 'footnotes', $footnotes );
102
+ }
103
+ }
104
+ }
105
+ add_action( 'wp_after_insert_post', 'wp_save_footnotes_meta' );
106
+
107
+ /**
108
+ * Keeps track of the revision ID for "rest_after_insert_{$post_type}".
109
+ *
110
+ * @since 6.3.0
111
+ *
112
+ * @global int $wp_temporary_footnote_revision_id The footnote revision ID.
113
+ *
114
+ * @param int $revision_id The revision ID.
115
+ */
116
+ function wp_keep_footnotes_revision_id( $revision_id ) {
117
+ global $wp_temporary_footnote_revision_id;
118
+ $wp_temporary_footnote_revision_id = $revision_id;
119
+ }
120
+ add_action( '_wp_put_post_revision', 'wp_keep_footnotes_revision_id' );
121
+
122
+ /**
123
+ * This is a specific fix for the REST API. The REST API doesn't update
124
+ * the post and post meta in one go (through `meta_input`). While it
125
+ * does fix the `wp_after_insert_post` hook to be called correctly after
126
+ * updating meta, it does NOT fix hooks such as post_updated and
127
+ * save_post, which are normally also fired after post meta is updated
128
+ * in `wp_insert_post()`. Unfortunately, `wp_save_post_revision` is
129
+ * added to the `post_updated` action, which means the meta is not
130
+ * available at the time, so we have to add it afterwards through the
131
+ * `"rest_after_insert_{$post_type}"` action.
132
+ *
133
+ * @since 6.3.0
134
+ *
135
+ * @global int $wp_temporary_footnote_revision_id The footnote revision ID.
136
+ *
137
+ * @param WP_Post $post The post object.
138
+ */
139
+ function wp_add_footnotes_revisions_to_post_meta( $post ) {
140
+ global $wp_temporary_footnote_revision_id;
141
+
142
+ if ( $wp_temporary_footnote_revision_id ) {
143
+ $revision = get_post( $wp_temporary_footnote_revision_id );
144
+
145
+ if ( ! $revision ) {
146
+ return;
147
+ }
148
+
149
+ $post_id = $revision->post_parent;
150
+
151
+ // Just making sure we're updating the right revision.
152
+ if ( $post->ID === $post_id ) {
153
+ $footnotes = get_post_meta( $post_id, 'footnotes', true );
154
+
155
+ if ( $footnotes ) {
156
+ // Can't use update_post_meta() because it doesn't allow revisions.
157
+ update_metadata( 'post', $wp_temporary_footnote_revision_id, 'footnotes', $footnotes );
158
+ }
159
+ }
160
+ }
161
+ }
162
+
163
+ foreach ( array( 'post', 'page' ) as $post_type ) {
164
+ add_action( "rest_after_insert_{$post_type}", 'wp_add_footnotes_revisions_to_post_meta' );
165
+ }
166
+
167
+ /**
168
+ * Restores the footnotes meta value from the revision.
169
+ *
170
+ * @since 6.3.0
171
+ *
172
+ * @param int $post_id The post ID.
173
+ * @param int $revision_id The revision ID.
174
+ */
175
+ function wp_restore_footnotes_from_revision( $post_id, $revision_id ) {
176
+ $footnotes = get_post_meta( $revision_id, 'footnotes', true );
177
+
178
+ if ( $footnotes ) {
179
+ update_post_meta( $post_id, 'footnotes', $footnotes );
180
+ } else {
181
+ delete_post_meta( $post_id, 'footnotes' );
182
+ }
183
+ }
184
+ add_action( 'wp_restore_post_revision', 'wp_restore_footnotes_from_revision', 10, 2 );
185
+
186
+ /**
187
+ * Adds the footnotes field to the revision.
188
+ *
189
+ * @since 6.3.0
190
+ *
191
+ * @param array $fields The revision fields.
192
+ * @return array The revision fields.
193
+ */
194
+ function wp_add_footnotes_to_revision( $fields ) {
195
+ $fields['footnotes'] = __( 'Footnotes' );
196
+ return $fields;
197
+ }
198
+ add_filter( '_wp_post_revision_fields', 'wp_add_footnotes_to_revision' );
199
+
200
+ /**
201
+ * Gets the footnotes field from the revision.
202
+ *
203
+ * @since 6.3.0
204
+ *
205
+ * @param string $revision_field The field value, but $revision->$field
206
+ * (footnotes) does not exist.
207
+ * @param string $field The field name, in this case "footnotes".
208
+ * @param object $revision The revision object to compare against.
209
+ * @return string The field value.
210
+ */
211
+ function wp_get_footnotes_from_revision( $revision_field, $field, $revision ) {
212
+ return get_metadata( 'post', $revision->ID, $field, true );
213
+ }
214
+ add_filter( '_wp_post_revision_field_footnotes', 'wp_get_footnotes_from_revision', 10, 3 );
215
+
216
+ /**
217
+ * The REST API autosave endpoint doesn't save meta, so we can use the
218
+ * `wp_creating_autosave` when it updates an exiting autosave, and
219
+ * `_wp_put_post_revision` when it creates a new autosave.
220
+ *
221
+ * @since 6.3.0
222
+ *
223
+ * @param int|array $autosave The autosave ID or array.
224
+ */
225
+ function _wp_rest_api_autosave_meta( $autosave ) {
226
+ // Ensure it's a REST API request.
227
+ if ( ! defined( 'REST_REQUEST' ) || ! REST_REQUEST ) {
228
+ return;
229
+ }
230
+
231
+ $body = rest_get_server()->get_raw_data();
232
+ $body = json_decode( $body, true );
233
+
234
+ if ( ! isset( $body['meta']['footnotes'] ) ) {
235
+ return;
236
+ }
237
+
238
+ // `wp_creating_autosave` passes the array,
239
+ // `_wp_put_post_revision` passes the ID.
240
+ $id = is_int( $autosave ) ? $autosave : $autosave['ID'];
241
+
242
+ if ( ! $id ) {
243
+ return;
244
+ }
245
+
246
+ update_post_meta( $id, 'footnotes', $body['meta']['footnotes'] );
247
+ }
248
+ // See https://github.com/WordPress/wordpress-develop/blob/2103cb9966e57d452c94218bbc3171579b536a40/src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php#L391C1-L391C1.
249
+ add_action( 'wp_creating_autosave', '_wp_rest_api_autosave_meta' );
250
+ // See https://github.com/WordPress/wordpress-develop/blob/2103cb9966e57d452c94218bbc3171579b536a40/src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php#L398.
251
+ // Then https://github.com/WordPress/wordpress-develop/blob/2103cb9966e57d452c94218bbc3171579b536a40/src/wp-includes/revision.php#L367.
252
+ add_action( '_wp_put_post_revision', '_wp_rest_api_autosave_meta' );
253
+
254
+ /**
255
+ * This is a workaround for the autosave endpoint returning early if the
256
+ * revision field are equal. The problem is that "footnotes" is not real
257
+ * revision post field, so there's nothing to compare against.
258
+ *
259
+ * This trick sets the "footnotes" field (value doesn't matter), which will
260
+ * cause the autosave endpoint to always update the latest revision. That should
261
+ * be fine, it should be ok to update the revision even if nothing changed. Of
262
+ * course, this is temporary fix.
263
+ *
264
+ * @since 6.3.0
265
+ *
266
+ * @param WP_Post $prepared_post The prepared post object.
267
+ * @param WP_REST_Request $request The request object.
268
+ *
269
+ * See https://github.com/WordPress/wordpress-develop/blob/2103cb9966e57d452c94218bbc3171579b536a40/src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php#L365-L384.
270
+ * See https://github.com/WordPress/wordpress-develop/blob/2103cb9966e57d452c94218bbc3171579b536a40/src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php#L219.
271
+ */
272
+ function _wp_rest_api_force_autosave_difference( $prepared_post, $request ) {
273
+ // We only want to be altering POST requests.
274
+ if ( $request->get_method() !== 'POST' ) {
275
+ return $prepared_post;
276
+ }
277
+
278
+ // Only alter requests for the '/autosaves' route.
279
+ if ( substr( $request->get_route(), -strlen( '/autosaves' ) ) !== '/autosaves' ) {
280
+ return $prepared_post;
281
+ }
282
+
283
+ $prepared_post->footnotes = '[]';
284
+ return $prepared_post;
285
+ }
286
+
287
+ add_filter( 'rest_pre_insert_post', '_wp_rest_api_force_autosave_difference', 10, 2 );
@@ -1,17 +1,20 @@
1
+ // These styles are for backwards compatibility with the old footnotes anchors.
2
+ // Can be removed in the future.
1
3
  .editor-styles-wrapper,
2
4
  .entry-content {
3
5
  counter-reset: footnotes;
4
6
  }
5
7
 
6
- [data-fn].fn {
8
+ a[data-fn].fn {
7
9
  vertical-align: super;
8
10
  font-size: smaller;
9
11
  counter-increment: footnotes;
10
- display: inline-block;
12
+ display: inline-flex;
13
+ text-decoration: none;
11
14
  text-indent: -9999999px;
12
15
  }
13
16
 
14
- [data-fn].fn::after {
17
+ a[data-fn].fn::after {
15
18
  content: "[" counter(footnotes) "]";
16
19
  text-indent: 0;
17
20
  float: left;
@@ -91,6 +91,7 @@ function GalleryEdit( props ) {
91
91
  isSelected,
92
92
  insertBlocksAfter,
93
93
  isContentLocked,
94
+ onFocus,
94
95
  } = props;
95
96
 
96
97
  const { columns, imageCrop, linkTarget, linkTo, sizeSlug, caption } =
@@ -498,6 +499,7 @@ function GalleryEdit( props ) {
498
499
  value: hasImageIds ? images : {},
499
500
  autoOpenMediaUpload:
500
501
  ! hasImages && isSelected && wasBlockJustInserted,
502
+ onFocus,
501
503
  },
502
504
  } );
503
505
  const mediaPlaceholder = (
@@ -562,7 +564,7 @@ function GalleryEdit( props ) {
562
564
  max={ Math.min( MAX_COLUMNS, images.length ) }
563
565
  { ...MOBILE_CONTROL_PROPS_RANGE_CONTROL }
564
566
  required
565
- size="__unstable-large"
567
+ __next40pxDefaultSize
566
568
  />
567
569
  ) }
568
570
  <ToggleControl
@@ -616,44 +618,46 @@ function GalleryEdit( props ) {
616
618
  ) }
617
619
  </PanelBody>
618
620
  </InspectorControls>
619
- <BlockControls group="block">
620
- { ! isContentLocked && (
621
- <ToolbarButton
622
- onClick={ () => {
623
- setShowCaption( ! showCaption );
624
- if ( showCaption && caption ) {
625
- setAttributes( { caption: undefined } );
626
- }
627
- } }
628
- icon={ captionIcon }
629
- isPressed={ showCaption }
630
- label={
631
- showCaption
632
- ? __( 'Remove caption' )
633
- : __( 'Add caption' )
634
- }
635
- />
636
- ) }
637
- </BlockControls>
638
- <BlockControls group="other">
639
- <MediaReplaceFlow
640
- allowedTypes={ ALLOWED_MEDIA_TYPES }
641
- accept="image/*"
642
- handleUpload={ false }
643
- onSelect={ updateImages }
644
- name={ __( 'Add' ) }
645
- multiple={ true }
646
- mediaIds={ images
647
- .filter( ( image ) => image.id )
648
- .map( ( image ) => image.id ) }
649
- addToGallery={ hasImageIds }
650
- />
651
- </BlockControls>
652
621
  { Platform.isWeb && (
653
- <GapStyles
654
- blockGap={ attributes.style?.spacing?.blockGap }
655
- clientId={ clientId }
656
- />
622
+ <>
623
+ <BlockControls group="block">
624
+ { ! isContentLocked && (
625
+ <ToolbarButton
626
+ onClick={ () => {
627
+ setShowCaption( ! showCaption );
628
+ if ( showCaption && caption ) {
629
+ setAttributes( { caption: undefined } );
630
+ }
631
+ } }
632
+ icon={ captionIcon }
633
+ isPressed={ showCaption }
634
+ label={
635
+ showCaption
636
+ ? __( 'Remove caption' )
637
+ : __( 'Add caption' )
638
+ }
639
+ />
640
+ ) }
641
+ </BlockControls>
642
+ <BlockControls group="other">
643
+ <MediaReplaceFlow
644
+ allowedTypes={ ALLOWED_MEDIA_TYPES }
645
+ accept="image/*"
646
+ handleUpload={ false }
647
+ onSelect={ updateImages }
648
+ name={ __( 'Add' ) }
649
+ multiple={ true }
650
+ mediaIds={ images
651
+ .filter( ( image ) => image.id )
652
+ .map( ( image ) => image.id ) }
653
+ addToGallery={ hasImageIds }
654
+ />
655
+ </BlockControls>
656
+ <GapStyles
657
+ blockGap={ attributes.style?.spacing?.blockGap }
658
+ clientId={ clientId }
659
+ />
660
+ </>
657
661
  ) }
658
662
  <Gallery
659
663
  { ...props }