Full Site Editing - Version 0.18.1

Version Description

  • Blog Posts Block: Tag Exclusion feature
  • Blog Posts Block: Image orientation issues resolved.
  • Blog Posts Block: Full width alignment issue resolved.
Download this release

Release Info

Developer rabberson
Plugin Icon wp plugin Full Site Editing
Version 0.18.1
Comparing to
See all releases

Code changes from version 0.18 to 0.18.1

Files changed (181) hide show
  1. {trunk/event-countdown-block → event-countdown-block}/blocks/event-countdown.js +0 -0
  2. {trunk/event-countdown-block → event-countdown-block}/blocks/event-countdown.php +0 -0
  3. {trunk/event-countdown-block → event-countdown-block}/editor.css +0 -0
  4. {trunk/event-countdown-block → event-countdown-block}/index.asset.php +0 -0
  5. {trunk/event-countdown-block → event-countdown-block}/index.js +0 -0
  6. {trunk/event-countdown-block → event-countdown-block}/index.php +0 -0
  7. {trunk/event-countdown-block → event-countdown-block}/license.txt +0 -0
  8. {trunk/event-countdown-block → event-countdown-block}/style.css +0 -0
  9. full-site-editing-plugin.php +2 -2
  10. {trunk/jetpack-timeline → jetpack-timeline}/blocks/timeline.php +0 -0
  11. {trunk/jetpack-timeline → jetpack-timeline}/editor.css +0 -0
  12. {trunk/jetpack-timeline → jetpack-timeline}/index.asset.php +0 -0
  13. {trunk/jetpack-timeline → jetpack-timeline}/index.js +0 -0
  14. {trunk/jetpack-timeline → jetpack-timeline}/index.php +0 -0
  15. {trunk/jetpack-timeline → jetpack-timeline}/style.css +0 -0
  16. readme.txt +2 -2
  17. trunk/blog-posts-block/README.md +0 -32
  18. trunk/blog-posts-block/dist/editor.asset.php +0 -1
  19. trunk/blog-posts-block/dist/editor.css +0 -1
  20. trunk/blog-posts-block/dist/editor.js +0 -2
  21. trunk/blog-posts-block/dist/editor.js.LICENSE +0 -5
  22. trunk/blog-posts-block/dist/editor.rtl.css +0 -1
  23. trunk/blog-posts-block/dist/view.asset.php +0 -1
  24. trunk/blog-posts-block/dist/view.css +0 -1
  25. trunk/blog-posts-block/dist/view.js +0 -1
  26. trunk/blog-posts-block/dist/view.rtl.css +0 -1
  27. trunk/blog-posts-block/editor.js +0 -38
  28. trunk/blog-posts-block/index.php +0 -92
  29. trunk/blog-posts-block/newspack-homepage-articles/README.md +0 -5
  30. trunk/blog-posts-block/newspack-homepage-articles/blocks/homepage-articles/block.json +0 -127
  31. trunk/blog-posts-block/newspack-homepage-articles/blocks/homepage-articles/class-wp-rest-newspack-articles-controller.php +0 -143
  32. trunk/blog-posts-block/newspack-homepage-articles/blocks/homepage-articles/edit.js +0 -677
  33. trunk/blog-posts-block/newspack-homepage-articles/blocks/homepage-articles/editor.js +0 -7
  34. trunk/blog-posts-block/newspack-homepage-articles/blocks/homepage-articles/editor.scss +0 -39
  35. trunk/blog-posts-block/newspack-homepage-articles/blocks/homepage-articles/index.js +0 -106
  36. trunk/blog-posts-block/newspack-homepage-articles/blocks/homepage-articles/templates/article.php +0 -143
  37. trunk/blog-posts-block/newspack-homepage-articles/blocks/homepage-articles/templates/articles-list.php +0 -21
  38. trunk/blog-posts-block/newspack-homepage-articles/blocks/homepage-articles/templates/articles-loop.php +0 -29
  39. trunk/blog-posts-block/newspack-homepage-articles/blocks/homepage-articles/view.js +0 -236
  40. trunk/blog-posts-block/newspack-homepage-articles/blocks/homepage-articles/view.php +0 -227
  41. trunk/blog-posts-block/newspack-homepage-articles/blocks/homepage-articles/view.scss +0 -582
  42. trunk/blog-posts-block/newspack-homepage-articles/class-newspack-blocks-api.php +0 -224
  43. trunk/blog-posts-block/newspack-homepage-articles/class-newspack-blocks.php +0 -407
  44. trunk/blog-posts-block/newspack-homepage-articles/components/autocomplete-tokenfield.js +0 -175
  45. trunk/blog-posts-block/newspack-homepage-articles/components/autocomplete-tokenfield.scss +0 -9
  46. trunk/blog-posts-block/newspack-homepage-articles/components/query-controls.js +0 -254
  47. trunk/blog-posts-block/newspack-homepage-articles/shared/sass/_colors.scss +0 -8
  48. trunk/blog-posts-block/newspack-homepage-articles/shared/sass/_legacy_colors.scss +0 -13
  49. trunk/blog-posts-block/newspack-homepage-articles/shared/sass/_mixins.scss +0 -26
  50. trunk/blog-posts-block/newspack-homepage-articles/shared/sass/_variables.scss +0 -27
  51. trunk/blog-posts-block/view.js +0 -1
  52. trunk/full-site-editing-plugin.php +0 -213
  53. trunk/full-site-editing/blocks/navigation-menu/edit.js +0 -98
  54. trunk/full-site-editing/blocks/navigation-menu/index.js +0 -33
  55. trunk/full-site-editing/blocks/navigation-menu/index.php +0 -125
  56. trunk/full-site-editing/blocks/navigation-menu/style.scss +0 -3
  57. trunk/full-site-editing/blocks/post-content/edit.js +0 -62
  58. trunk/full-site-editing/blocks/post-content/index.js +0 -57
  59. trunk/full-site-editing/blocks/post-content/index.php +0 -39
  60. trunk/full-site-editing/blocks/post-content/save.js +0 -6
  61. trunk/full-site-editing/blocks/post-content/style.scss +0 -69
  62. trunk/full-site-editing/blocks/site-credit/edit.js +0 -75
  63. trunk/full-site-editing/blocks/site-credit/footer-credit-choices.js +0 -24
  64. trunk/full-site-editing/blocks/site-credit/index.js +0 -38
  65. trunk/full-site-editing/blocks/site-credit/index.php +0 -205
  66. trunk/full-site-editing/blocks/site-credit/style.scss +0 -37
  67. trunk/full-site-editing/blocks/site-description/edit.js +0 -140
  68. trunk/full-site-editing/blocks/site-description/index.js +0 -61
  69. trunk/full-site-editing/blocks/site-description/index.php +0 -68
  70. trunk/full-site-editing/blocks/site-description/style.scss +0 -12
  71. trunk/full-site-editing/blocks/site-title/edit.js +0 -121
  72. trunk/full-site-editing/blocks/site-title/index.js +0 -50
  73. trunk/full-site-editing/blocks/site-title/index.php +0 -62
  74. trunk/full-site-editing/blocks/site-title/style.scss +0 -12
  75. trunk/full-site-editing/blocks/template/edit.js +0 -201
  76. trunk/full-site-editing/blocks/template/index.js +0 -60
  77. trunk/full-site-editing/blocks/template/index.php +0 -41
  78. trunk/full-site-editing/blocks/template/site-logo.js +0 -18
  79. trunk/full-site-editing/blocks/template/style.scss +0 -102
  80. trunk/full-site-editing/class-full-site-editing.php +0 -628
  81. trunk/full-site-editing/dist/full-site-editing.asset.php +0 -1
  82. trunk/full-site-editing/dist/full-site-editing.css +0 -1
  83. trunk/full-site-editing/dist/full-site-editing.js +0 -2
  84. trunk/full-site-editing/dist/full-site-editing.js.LICENSE +0 -5
  85. trunk/full-site-editing/dist/full-site-editing.rtl.css +0 -1
  86. trunk/full-site-editing/editor/block-inserter/index.js +0 -39
  87. trunk/full-site-editing/editor/block-inserter/post-content-block-appender.js +0 -27
  88. trunk/full-site-editing/editor/image-block-keywords/index.js +0 -23
  89. trunk/full-site-editing/editor/index.js +0 -10
  90. trunk/full-site-editing/editor/remove-editor-panels/index.js +0 -31
  91. trunk/full-site-editing/editor/style.scss +0 -95
  92. trunk/full-site-editing/editor/suppress-draft-action/index.js +0 -38
  93. trunk/full-site-editing/editor/suppress-trash-action/index.js +0 -26
  94. trunk/full-site-editing/editor/template-validity-override/index.js +0 -23
  95. trunk/full-site-editing/helpers.php +0 -181
  96. trunk/full-site-editing/index.js +0 -13
  97. trunk/full-site-editing/lib/index.js +0 -1
  98. trunk/full-site-editing/lib/site-options/index.js +0 -2
  99. trunk/full-site-editing/lib/site-options/use-previous.js +0 -24
  100. trunk/full-site-editing/lib/site-options/use-site-options.js +0 -127
  101. trunk/full-site-editing/lib/site-options/with-site-options.js +0 -99
  102. trunk/full-site-editing/plugins/close-button-override/index.js +0 -100
  103. trunk/full-site-editing/plugins/close-button-override/style.scss +0 -50
  104. trunk/full-site-editing/plugins/editor-template-classes/index.js +0 -53
  105. trunk/full-site-editing/plugins/template-update-notice/index.js +0 -20
  106. trunk/full-site-editing/sass/_mixins.scss +0 -17
  107. trunk/full-site-editing/serialize-block-fallback.php +0 -70
  108. trunk/full-site-editing/templates/class-rest-templates-controller.php +0 -49
  109. trunk/full-site-editing/templates/class-template-image-inserter.php +0 -174
  110. trunk/full-site-editing/templates/class-wp-template-inserter.php +0 -537
  111. trunk/full-site-editing/templates/class-wp-template.php +0 -204
  112. trunk/global-styles/README-DATA.md +0 -363
  113. trunk/global-styles/README.md +0 -230
  114. trunk/global-styles/class-global-styles.php +0 -515
  115. trunk/global-styles/dist/global-styles.asset.php +0 -1
  116. trunk/global-styles/dist/global-styles.css +0 -1
  117. trunk/global-styles/dist/global-styles.js +0 -2
  118. trunk/global-styles/dist/global-styles.js.LICENSE +0 -5
  119. trunk/global-styles/dist/global-styles.rtl.css +0 -1
  120. trunk/global-styles/editor.scss +0 -2
  121. trunk/global-styles/includes/class-data-point-literal.php +0 -44
  122. trunk/global-styles/includes/class-data-point-option.php +0 -104
  123. trunk/global-styles/includes/class-data-point-theme.php +0 -92
  124. trunk/global-styles/includes/class-data-set.php +0 -167
  125. trunk/global-styles/includes/class-json-endpoint.php +0 -116
  126. trunk/global-styles/includes/interface-data-point.php +0 -17
  127. trunk/global-styles/index.js +0 -51
  128. trunk/global-styles/src/constants.js +0 -7
  129. trunk/global-styles/src/dom-updater.js +0 -36
  130. trunk/global-styles/src/font-pairings-panel-previews.js +0 -73
  131. trunk/global-styles/src/font-pairings-panel.js +0 -50
  132. trunk/global-styles/src/font-pairings-panel.scss +0 -48
  133. trunk/global-styles/src/font-selection-panel.js +0 -49
  134. trunk/global-styles/src/global-styles-sidebar.js +0 -144
  135. trunk/global-styles/src/global-styles-sidebar.scss +0 -22
  136. trunk/global-styles/src/icon.js +0 -12
  137. trunk/global-styles/src/no-support.js +0 -11
  138. trunk/global-styles/src/store.js +0 -122
  139. trunk/global-styles/static/blank.css +0 -6
  140. trunk/global-styles/static/style.css +0 -28
  141. trunk/posts-list-block/blocks/posts-list/block.json +0 -10
  142. trunk/posts-list-block/blocks/posts-list/editor.scss +0 -9
  143. trunk/posts-list-block/blocks/posts-list/index.js +0 -110
  144. trunk/posts-list-block/blocks/posts-list/style.scss +0 -9
  145. trunk/posts-list-block/blocks/posts-list/transforms.js +0 -34
  146. trunk/posts-list-block/class-posts-list-block.php +0 -160
  147. trunk/posts-list-block/dist/posts-list-block.asset.php +0 -1
  148. trunk/posts-list-block/dist/posts-list-block.css +0 -1
  149. trunk/posts-list-block/dist/posts-list-block.js +0 -1
  150. trunk/posts-list-block/dist/posts-list-block.rtl.css +0 -1
  151. trunk/posts-list-block/index.js +0 -4
  152. trunk/posts-list-block/templates/no-posts.php +0 -26
  153. trunk/posts-list-block/templates/post-item.php +0 -44
  154. trunk/posts-list-block/templates/posts-list.php +0 -39
  155. trunk/posts-list-block/utils.php +0 -46
  156. trunk/readme.txt +0 -136
  157. trunk/starter-page-templates/class-starter-page-templates.php +0 -262
  158. trunk/starter-page-templates/class-wp-rest-sideload-image-controller.php +0 -294
  159. trunk/starter-page-templates/dist/starter-page-templates.asset.php +0 -1
  160. trunk/starter-page-templates/dist/starter-page-templates.css +0 -1
  161. trunk/starter-page-templates/dist/starter-page-templates.js +0 -2
  162. trunk/starter-page-templates/dist/starter-page-templates.js.LICENSE +0 -5
  163. trunk/starter-page-templates/dist/starter-page-templates.rtl.css +0 -1
  164. trunk/starter-page-templates/index.js +0 -87
  165. trunk/starter-page-templates/page-template-modal/components/block-preview.js +0 -27
  166. trunk/starter-page-templates/page-template-modal/components/block-template-preview.js +0 -34
  167. trunk/starter-page-templates/page-template-modal/components/preview-template-title.js +0 -22
  168. trunk/starter-page-templates/page-template-modal/components/sidebar-modal-opener.js +0 -124
  169. trunk/starter-page-templates/page-template-modal/components/template-selector-control.js +0 -78
  170. trunk/starter-page-templates/page-template-modal/components/template-selector-item.js +0 -75
  171. trunk/starter-page-templates/page-template-modal/components/template-selector-preview.js +0 -145
  172. trunk/starter-page-templates/page-template-modal/components/test/__snapshots__/template-selector-control-test.js.snap +0 -128
  173. trunk/starter-page-templates/page-template-modal/components/test/__snapshots__/template-selector-preview-test.js.snap +0 -48
  174. trunk/starter-page-templates/page-template-modal/components/test/helpers/templates-blocks-helpers.js +0 -58
  175. trunk/starter-page-templates/page-template-modal/components/test/template-selector-control-test.js +0 -200
  176. trunk/starter-page-templates/page-template-modal/components/test/template-selector-preview-test.js +0 -65
  177. trunk/starter-page-templates/page-template-modal/index.js +0 -401
  178. trunk/starter-page-templates/page-template-modal/styles/starter-page-templates-editor.scss +0 -503
  179. trunk/starter-page-templates/page-template-modal/utils/ensure-assets.js +0 -213
  180. trunk/starter-page-templates/page-template-modal/utils/replace-placeholders.js +0 -32
  181. trunk/starter-page-templates/page-template-modal/utils/tracking.js +0 -59
{trunk/event-countdown-block → event-countdown-block}/blocks/event-countdown.js RENAMED
File without changes
{trunk/event-countdown-block → event-countdown-block}/blocks/event-countdown.php RENAMED
File without changes
{trunk/event-countdown-block → event-countdown-block}/editor.css RENAMED
File without changes
{trunk/event-countdown-block → event-countdown-block}/index.asset.php RENAMED
File without changes
{trunk/event-countdown-block → event-countdown-block}/index.js RENAMED
File without changes
{trunk/event-countdown-block → event-countdown-block}/index.php RENAMED
File without changes
{trunk/event-countdown-block → event-countdown-block}/license.txt RENAMED
File without changes
{trunk/event-countdown-block → event-countdown-block}/style.css RENAMED
File without changes
full-site-editing-plugin.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Plugin Name: Full Site Editing
4
  * Description: Enhances your page creation workflow within the Block Editor.
5
- * Version: 0.18
6
  * Author: Automattic
7
  * Author URI: https://automattic.com/wordpress-plugins/
8
  * License: GPLv2 or later
@@ -35,7 +35,7 @@ namespace A8C\FSE;
35
  *
36
  * @var string
37
  */
38
- define( 'PLUGIN_VERSION', '0.18' );
39
 
40
  // Always include these helper files for FSE.
41
  require_once __DIR__ . '/full-site-editing/helpers.php';
2
  /**
3
  * Plugin Name: Full Site Editing
4
  * Description: Enhances your page creation workflow within the Block Editor.
5
+ * Version: 0.18.1
6
  * Author: Automattic
7
  * Author URI: https://automattic.com/wordpress-plugins/
8
  * License: GPLv2 or later
35
  *
36
  * @var string
37
  */
38
+ define( 'PLUGIN_VERSION', '0.18.1' );
39
 
40
  // Always include these helper files for FSE.
41
  require_once __DIR__ . '/full-site-editing/helpers.php';
{trunk/jetpack-timeline → jetpack-timeline}/blocks/timeline.php RENAMED
File without changes
{trunk/jetpack-timeline → jetpack-timeline}/editor.css RENAMED
File without changes
{trunk/jetpack-timeline → jetpack-timeline}/index.asset.php RENAMED
File without changes
{trunk/jetpack-timeline → jetpack-timeline}/index.js RENAMED
File without changes
{trunk/jetpack-timeline → jetpack-timeline}/index.php RENAMED
File without changes
{trunk/jetpack-timeline → jetpack-timeline}/style.css RENAMED
File without changes
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: alexislloyd, allancole, automattic, codebykat, copons, dmsnell, ge
3
  Tags: block, blocks, editor, gutenberg, page
4
  Requires at least: 5.0
5
  Tested up to: 5.3
6
- Stable tag: 0.18
7
  Requires PHP: 5.6.20
8
  License: GPLv2 or later
9
  License URI: https://www.gnu.org/licenses/gpl-2.0.html
@@ -42,7 +42,7 @@ This plugin is experimental, so we don't provide any support for it outside of w
42
 
43
  == Changelog ==
44
 
45
- = 0.18 =
46
  * Blog Posts Block: Tag Exclusion feature
47
  * Blog Posts Block: Image orientation issues resolved.
48
  * Blog Posts Block: Full width alignment issue resolved.
3
  Tags: block, blocks, editor, gutenberg, page
4
  Requires at least: 5.0
5
  Tested up to: 5.3
6
+ Stable tag: 0.18.1
7
  Requires PHP: 5.6.20
8
  License: GPLv2 or later
9
  License URI: https://www.gnu.org/licenses/gpl-2.0.html
42
 
43
  == Changelog ==
44
 
45
+ = 0.18.1 =
46
  * Blog Posts Block: Tag Exclusion feature
47
  * Blog Posts Block: Image orientation issues resolved.
48
  * Blog Posts Block: Full width alignment issue resolved.
trunk/blog-posts-block/README.md DELETED
@@ -1,32 +0,0 @@
1
- # Blog Posts Block
2
-
3
- This block allows you to list your posts in various layouts and filter them by criteria like category, tag or author.
4
-
5
- It originally comes from the [Newspack Blocks collection](https://github.com/automattic/newspack-blocks) and the block is still being developed there.
6
-
7
- It was added to this repository in order to make it available to other parts of the FSE plugin, such as Starter Page Templates where this block will be used.
8
-
9
- ## Structure
10
-
11
- ```
12
- index.php — main entry file, registers the block on backend
13
- editor.js — assets for the block editor
14
- view.js — assets for the block rendered on frontend
15
- newspack-homepage-articles/** — source code synced from the Newspack Blocks repository
16
- ```
17
-
18
- `editor.js`, `view.js` and `index.php` are files written in order to bridge the parent plugin with the Blog Posts Block. It changes the block name to `a8c/blog-posts` and does things like registering REST fields or styles and scripts. In these files we are free to do all those changes because they are not shared with Newspack and only live here in this repository.
19
-
20
- ### Synchronizing the code
21
-
22
- You can see that `newspack-homepage-articles` is being synced with the Newspack Blocks repository. Please make all improvements and additions on the Newspack side. Please don't make any direct changes to files in this directory as the next synchronization will overwrite them.
23
-
24
- Once your changes land on the Newspack side, coordinate with the team (over issues/PRs) to [make a new release](https://github.com/Automattic/newspack-blocks/releases) and once you have the release ID, you can pull the code into here.
25
-
26
- While being in `apps/full-site-editing/` directory, you can run:
27
-
28
- ```
29
- npm run sync:blog-posts-block --release=1.0.0-alpha.17
30
- ```
31
-
32
- This will pull the code from the release and integrate it into this repository. Please review changes, make sure to update `NEWSPACK_BLOCKS__VERSION` in [index.php](./index.php) and commit.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/blog-posts-block/dist/editor.asset.php DELETED
@@ -1 +0,0 @@
1
- <?php return array('dependencies' => array('lodash', 'moment', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n', 'wp-polyfill', 'wp-url'), 'version' => '3614c7b88f9588d96d19edc1a82772b4');
 
trunk/blog-posts-block/dist/editor.css DELETED
@@ -1 +0,0 @@
1
- .autocomplete-tokenfield{position:relative}.autocomplete-tokenfield .components-spinner{position:absolute;top:2em;right:0}.type-scale-slider .dashicon{height:16px;width:16px}.type-scale-slider input+.dashicon{height:24px;margin-left:10px;margin-right:0;width:24px}.wpnbha .editor-rich-text{width:100%}.wpnbha .cat-links{font-size:.7em}.wpnbha span.avatar{display:inline-block;margin-right:.5em}.wpnbha span.avatar div{display:inline}.wpnbha .excerpt-contain p{margin:.5em 0}.wpnbha{margin-bottom:1em}.wpnbha article{margin-bottom:1.5em;word-break:break-word;overflow-wrap:break-word;position:relative}.wpnbha article:last-of-type{margin-bottom:0}.wpnbha .article-section-title{font-size:.8em;margin-bottom:.5em;width:100%}.wpnbha.is-grid>div{display:flex;flex-wrap:wrap;justify-content:space-between;padding:0;list-style:none}.wpnbha.is-grid article{flex-basis:100%}@media only screen and (min-width:782px){.wpnbha.is-grid article,.wpnbha.is-grid article:last-child{margin-bottom:1em}}@media only screen and (min-width:600px){.wpnbha.columns-3 article,.wpnbha.columns-6 article{flex-basis:calc(33.333% - 16px)}.wpnbha.columns-2 article,.wpnbha.columns-4 article,.wpnbha.columns-5 article{flex-basis:calc(50% - 16px)}.wpnbha.columns-5 article:last-of-type:nth-child(odd){flex-grow:1}}@media only screen and (min-width:782px){.wpnbha.columns-2 article{flex-basis:calc(50% - 16px)}.wpnbha.columns-3 article{flex-basis:calc(33.33333% - 16px)}.wpnbha.columns-4 article{flex-basis:calc(25% - 16px)}.wpnbha.columns-5 article{flex-basis:calc(20% - 16px)}.wpnbha.columns-6 article{flex-basis:calc(16.66667% - 16px)}}.wpnbha .post-thumbnail{margin:0}.wpnbha .post-thumbnail img{height:auto;width:100%}.wpnbha figcaption{font-size:.6em}.wpnbha .post-thumbnail{margin-bottom:.25em}.wpnbha .post-thumbnail figcaption{margin-bottom:.5em}.wpnbha.image-alignleft .post-has-image,.wpnbha.image-alignright .post-has-image{display:flex}.wpnbha.image-alignleft .post-has-image .post-thumbnail,.wpnbha.image-alignright .post-has-image .post-thumbnail{flex-basis:33%}.wpnbha.image-alignleft .post-has-image .entry-wrapper,.wpnbha.image-alignright .post-has-image .entry-wrapper{flex-basis:67%}.wpnbha.image-alignleft.mobile-stack .post-has-image,.wpnbha.image-alignright.mobile-stack .post-has-image{display:block}@media only screen and (min-width:600px){.wpnbha.image-alignleft.mobile-stack .post-has-image,.wpnbha.image-alignright.mobile-stack .post-has-image{display:flex}}@media only screen and (min-width:600px){.wpnbha.image-alignleft.is-4 .post-thumbnail,.wpnbha.image-alignright.is-4 .post-thumbnail{flex-basis:75%}.wpnbha.image-alignleft.is-4 .entry-wrapper,.wpnbha.image-alignright.is-4 .entry-wrapper{flex-basis:25%}.wpnbha.image-alignleft.is-3 .entry-wrapper,.wpnbha.image-alignleft.is-3 .post-thumbnail,.wpnbha.image-alignright.is-3 .entry-wrapper,.wpnbha.image-alignright.is-3 .post-thumbnail{flex-basis:50%}}.wpnbha.image-alignleft.is-1 .post-thumbnail,.wpnbha.image-alignright.is-1 .post-thumbnail{flex-basis:25%}.wpnbha.image-alignleft.is-1 .entry-wrapper,.wpnbha.image-alignright.is-1 .entry-wrapper{flex-basis:75%}.wpnbha.image-alignleft .post-thumbnail{margin-right:1em}.wpnbha.image-alignright .post-thumbnail{margin-left:1em}.wpnbha.image-alignright .entry-wrapper{order:-1}.wpnbha.mobile-stack.image-alignleft .post-thumbnail,.wpnbha.mobile-stack.image-alignright .post-thumbnail{margin-left:0;margin-right:0}@media only screen and (min-width:600px){.wpnbha.mobile-stack.image-alignleft .post-thumbnail{margin-right:1em}.wpnbha.mobile-stack.image-alignright .post-thumbnail{margin-left:1em}}.wpnbha .entry-title{margin:0 0 .25em}.wpnbha .entry-title a{color:inherit;text-decoration:none}.wpnbha .cat-links{font-size:.6em;font-weight:700;margin:0 0 .5em}.wpnbha .cat-links a{text-decoration:none}.wpnbha .cat-links a:hover{text-decoration:underline}.wpnbha .entry-meta{display:flex;flex-wrap:wrap;align-items:center;margin-top:.5em}.wpnbha .entry-meta .byline:not(:last-child){margin-right:1.5em}.wpnbha .entry-meta .updated:not(.published){display:none}.wpnbha .avatar{border-radius:100%;display:block;margin-right:.5em}.wpnbha p{margin:.5em 0}.wpnbha.has-text-color .article-section-title,.wpnbha.has-text-color .cat-links,.wpnbha.has-text-color .cat-links a,.wpnbha.has-text-color .cat-links a:visited,.wpnbha.has-text-color .entry-meta,.wpnbha.has-text-color .entry-meta .byline a,.wpnbha.has-text-color .entry-meta .byline a:visited,.wpnbha.has-text-color .entry-meta a,.wpnbha.has-text-color .entry-title,.wpnbha.has-text-color .entry-title a,.wpnbha.has-text-color .entry-title a:visited,.wpnbha.has-text-color figcaption{color:inherit}.wpnbha.has-text-color .entry-meta span:not(.avatar){opacity:.8}.wpnbha.image-alignbehind .post-has-image{display:flex;align-items:flex-end;position:relative}.wpnbha.image-alignbehind .post-has-image .post-thumbnail{bottom:0;left:0;margin:0;overflow:hidden;position:absolute;right:0;top:0}.wpnbha.image-alignbehind .post-has-image .post-thumbnail img{height:100%;-o-object-fit:cover;object-fit:cover;max-width:1000%;width:100%}.wpnbha.image-alignbehind .post-has-image .post-thumbnail figcaption{bottom:1em;-webkit-box-orient:vertical;color:hsla(0,0%,100%,.9);display:-webkit-box;font-style:italic;left:0;-webkit-line-clamp:1;margin:0;max-height:1.6em;overflow:hidden;padding:0 1em;position:absolute;right:0;text-align:right;text-overflow:ellipsis;z-index:2}.wpnbha.image-alignbehind .post-has-image .post-thumbnail:after{background:rgba(0,0,0,.5);bottom:0;content:"";left:0;position:absolute;right:0;top:0;z-index:1}.wpnbha.image-alignbehind .post-has-image .entry-wrapper{padding:2em;position:relative;z-index:2}.wpnbha.image-alignbehind .post-has-image .cat-links a,.wpnbha.image-alignbehind .post-has-image .entry-meta,.wpnbha.image-alignbehind .post-has-image .entry-meta .byline a,.wpnbha.image-alignbehind .post-has-image .entry-title a,.wpnbha.image-alignbehind .post-has-image .entry-wrapper{color:#fff}.wpnbha article .entry-title{font-size:1.2em}.wpnbha article .entry-meta{font-size:.8em}.wpnbha article .avatar{height:25px;width:25px}@media only screen and (min-width:782px){.wpnbha article .entry-title{font-size:1.6em}.wpnbha article .avatar{height:40px;width:40px}}.wpnbha.ts-8 .entry-title,.wpnbha.ts-9 .entry-title,.wpnbha.ts-10 .entry-title{line-height:1.1em}@media only screen and (min-width:782px){.wpnbha.ts-8 article .avatar,.wpnbha.ts-9 article .avatar,.wpnbha.ts-10 article .avatar{height:2.4em;width:2.4em}}.wpnbha.ts-10 article .entry-title{font-size:2.6em}@media only screen and (min-width:782px){.wpnbha.ts-10 article .entry-title{font-size:3.6em}}@media only screen and (min-width:1168px){.wpnbha.ts-10 article .entry-title{font-size:4.8em}}.wpnbha.ts-9 article .entry-title{font-size:2.4em}@media only screen and (min-width:782px){.wpnbha.ts-9 article .entry-title{font-size:3.4em}}@media only screen and (min-width:1168px){.wpnbha.ts-9 article .entry-title{font-size:4.2em}}.wpnbha.ts-8 article .entry-title{font-size:2.2em}@media only screen and (min-width:782px){.wpnbha.ts-8 article .entry-title{font-size:3em}}@media only screen and (min-width:1168px){.wpnbha.ts-8 article .entry-title{font-size:3.6em}}.wpnbha.ts-7 article .entry-title{font-size:2em}@media only screen and (min-width:782px){.wpnbha.ts-7 article .entry-title{font-size:2.4em}.wpnbha.ts-7 article .avatar{height:48px;width:48px}}@media only screen and (min-width:1168px){.wpnbha.ts-7 article .entry-title{font-size:3em}}.wpnbha.ts-6 article .entry-title{font-size:1.7em}@media only screen and (min-width:782px){.wpnbha.ts-6 article .entry-title{font-size:2em}.wpnbha.ts-6 article .avatar{height:44px;width:44px}}@media only screen and (min-width:1168px){.wpnbha.ts-6 article .entry-title{font-size:2.4em}}.wpnbha.ts-5 article .entry-title{font-size:1.4em}@media only screen and (min-width:782px){.wpnbha.ts-5 article .entry-title{font-size:1.8em}.wpnbha.ts-5 article .avatar{height:40px;width:40px}}@media only screen and (min-width:1168px){.wpnbha.ts-5 article .entry-title{font-size:2em}}.wpnbha.ts-3 article .entry-title{font-size:1em}.wpnbha.ts-3 article .entry-wrapper p{font-size:.8em}.wpnbha.ts-3 article .entry-meta{font-size:.7em}@media only screen and (min-width:782px){.wpnbha.ts-3 article .entry-title{font-size:1.2em}.wpnbha.ts-3 article .avatar{height:32px;width:32px}}.wpnbha.ts-2 article .entry-title{font-size:.8em}.wpnbha.ts-2 article .entry-meta,.wpnbha.ts-2 article .entry-wrapper p{font-size:.7em}@media only screen and (min-width:782px){.wpnbha.ts-2 article .entry-title{font-size:.9em}.wpnbha.ts-2 article .avatar{height:28px;width:28px}}.wpnbha.ts-1 article .entry-title,.wpnbha.ts-1 article .entry-wrapper p{font-size:.7em}.wpnbha.ts-1 article .entry-meta{font-size:.6em}@media only screen and (min-width:782px){.wpnbha.ts-1 article .avatar{height:24px;width:24px}}.wpnbha.is-style-borders article{border:solid rgba(0,0,0,.2);border-width:0 0 1px;margin-bottom:1em;padding-bottom:1em}.wpnbha.is-style-borders article:last-of-type{margin-bottom:0}.wpnbha.is-style-borders article:last-of-type:not(:first-of-type){border-bottom:0}@media only screen and (min-width:782px){.wpnbha.is-style-borders.columns-2 article{padding-right:32px}.wpnbha.is-style-borders.columns-3 article{padding-right:24px}.wpnbha.is-style-borders.columns-4 article{padding-right:21.33333px}.wpnbha.is-style-borders.columns-5 article{padding-right:20px}.wpnbha.is-style-borders.columns-6 article{padding-right:19.2px}.wpnbha.is-style-borders.is-grid article{border-width:0 1px 0 0}.wpnbha.is-style-borders.columns-1 article,.wpnbha.is-style-borders.columns-2 article:nth-of-type(2n),.wpnbha.is-style-borders.columns-3 article:nth-of-type(3n),.wpnbha.is-style-borders.columns-4 article:nth-of-type(4n),.wpnbha.is-style-borders.columns-5 article:nth-of-type(5n),.wpnbha.is-style-borders.columns-6 article:nth-of-type(6n),.wpnbha.is-style-borders.is-grid article:last-of-type{border:0}}
 
trunk/blog-posts-block/dist/editor.js DELETED
@@ -1,2 +0,0 @@
1
- /*! For license information please see editor.js.LICENSE */
2
- !function(e,t){for(var n in t)e[n]=t[n]}(window,function(e){var t={};function n(o){if(t[o])return t[o].exports;var c=t[o]={i:o,l:!1,exports:{}};return e[o].call(c.exports,c,c.exports,n),c.l=!0,c.exports}return n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var c in e)n.d(o,c,function(t){return e[t]}.bind(null,c));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=33)}([function(e,t){!function(){e.exports=this.wp.element}()},function(e,t){!function(){e.exports=this.wp.i18n}()},function(e,t){!function(){e.exports=this.wp.components}()},function(e,t){e.exports=function(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}},function(e,t){e.exports=function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}},function(e,t){!function(){e.exports=this.wp.htmlEntities}()},function(e,t){!function(){e.exports=this.wp.url}()},function(e,t){!function(){e.exports=this.wp.apiFetch}()},function(e,t){!function(){e.exports=this.wp.blockEditor}()},function(e,t){e.exports=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}},function(e,t,n){var o=n(28),c=n(4);e.exports=function(e,t){return!t||"object"!==o(t)&&"function"!=typeof t?c(e):t}},function(e,t){function n(t){return e.exports=n=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)},n(t)}e.exports=n},function(e,t,n){var o=n(29);e.exports=function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&o(e,t)}},function(e,t){!function(){e.exports=this.wp.blocks}()},function(e,t){!function(){e.exports=this.lodash}()},function(e,t){!function(){e.exports=this.wp.hooks}()},function(e,t,n){var o=n(25),c=n(26),a=n(27);e.exports=function(e){return o(e)||c(e)||a()}},function(e,t){function n(e,t){for(var n=0;n<t.length;n++){var o=t[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}e.exports=function(e,t,o){return t&&n(e.prototype,t),o&&n(e,o),e}},function(e){e.exports=JSON.parse('{"name":"homepage-articles","category":"newspack","attributes":{"className":{"type":"string","default":""},"showExcerpt":{"type":"boolean","default":true},"showDate":{"type":"boolean","default":true},"showImage":{"type":"boolean","default":true},"showCaption":{"type":"boolean","default":false},"imageShape":{"type":"string","default":"landscape"},"minHeight":{"type":"integer","default":0},"moreButton":{"type":"boolean","default":false},"moreButtonText":{"type":"string","default":""},"showAuthor":{"type":"boolean","default":true},"showAvatar":{"type":"boolean","default":true},"showCategory":{"type":"boolean","default":false},"postLayout":{"type":"string","default":"list"},"columns":{"type":"integer","default":3},"postsToShow":{"type":"integer","default":3},"mediaPosition":{"type":"string","default":"top"},"authors":{"type":"array","default":[],"items":{"type":"integer"}},"categories":{"type":"array","default":[],"items":{"type":"integer"}},"tags":{"type":"array","default":[],"items":{"type":"integer"}},"tagExclusions":{"type":"array","default":[],"items":{"type":"integer"}},"specificPosts":{"type":"array","default":[],"items":{"type":"integer"}},"typeScale":{"type":"integer","default":4},"imageScale":{"type":"integer","default":3},"mobileStack":{"type":"boolean","default":false},"sectionHeader":{"type":"string","default":""},"specificMode":{"type":"boolean","default":false},"textColor":{"type":"string","default":""},"customTextColor":{"type":"string","default":""},"singleMode":{"type":"boolean","default":false}}}')},function(e,t,n){var o=n(3);function c(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,o)}return n}e.exports=function(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?c(Object(n),!0).forEach((function(t){o(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):c(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}},function(e,t){function n(){return e.exports=n=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var o in n)Object.prototype.hasOwnProperty.call(n,o)&&(e[o]=n[o])}return e},n.apply(this,arguments)}e.exports=n},function(e,t,n){var o;!function(){"use strict";var n={}.hasOwnProperty;function c(){for(var e=[],t=0;t<arguments.length;t++){var o=arguments[t];if(o){var a=typeof o;if("string"===a||"number"===a)e.push(o);else if(Array.isArray(o)&&o.length){var r=c.apply(null,o);r&&e.push(r)}else if("object"===a)for(var s in o)n.call(o,s)&&o[s]&&e.push(s)}}return e.join(" ")}e.exports?(c.default=c,e.exports=c):void 0===(o=function(){return c}.apply(t,[]))||(e.exports=o)}()},function(e,t){!function(){e.exports=this.moment}()},function(e,t){!function(){e.exports=this.wp.data}()},function(e,t){!function(){e.exports=this.wp.compose}()},function(e,t){e.exports=function(e){if(Array.isArray(e)){for(var t=0,n=new Array(e.length);t<e.length;t++)n[t]=e[t];return n}}},function(e,t){e.exports=function(e){if(Symbol.iterator in Object(e)||"[object Arguments]"===Object.prototype.toString.call(e))return Array.from(e)}},function(e,t){e.exports=function(){throw new TypeError("Invalid attempt to spread non-iterable instance")}},function(e,t){function n(t){return"function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?e.exports=n=function(e){return typeof e}:e.exports=n=function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},n(t)}e.exports=n},function(e,t){function n(t,o){return e.exports=n=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e},n(t,o)}e.exports=n},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){"use strict";n.r(t);var o=n(19),c=n.n(o),a=n(13),r=n(1),s=n(15),i=n(0),l=n(2),u=n(16),p=n.n(u),b=n(9),h=n.n(b),f=n(17),g=n.n(f),d=n(10),m=n.n(d),w=n(11),O=n.n(w),k=n(4),j=n.n(k),y=n(12),v=n.n(y),_=n(3),E=n.n(_),S=n(20),C=n.n(S),x=n(7),P=n.n(x),A=n(6),T=n(5),M=n(14),H=(n(30),function(e){function t(e){var n;return h()(this,t),(n=m()(this,O()(t).call(this,e))).state={suggestions:[],validValues:{},loading:!1},n.debouncedUpdateSuggestions=Object(M.debounce)(n.updateSuggestions,500),n}return v()(t,e),g()(t,[{key:"componentDidMount",value:function(){var e=this,t=this.props,n=t.tokens,o=t.fetchSavedInfo;n.length&&o&&this.setState({loading:!0},(function(){o(n).then((function(t){var n=e.state.validValues;t.forEach((function(e){n[e.value]=e.label})),e.setState({validValues:n,loading:!1})}))}))}},{key:"componentWillUnmount",value:function(){delete this.suggestionsRequest,this.debouncedUpdateSuggestions.cancel()}},{key:"getLabelsForValues",value:function(e){var t=this.state.validValues;return e.reduce((function(e,n){return t[n]?[].concat(p()(e),[t[n]]):e}),[])}},{key:"getValuesForLabels",value:function(e){var t=this.state.validValues;return e.map((function(e){return Object.keys(t).find((function(n){return t[n]===e}))}))}},{key:"updateSuggestions",value:function(e){var t=this,n=this.props.fetchSuggestions;n&&this.setState({loading:!0},(function(){var o=n(e);o.then((function(e){if(t.suggestionsRequest===o){var n=t.state.validValues,c=[];e.forEach((function(e){c.push(e.label),n[e.value]=e.label})),t.setState({suggestions:c,validValues:n,loading:!1})}})).catch((function(){t.suggestionsRequest===o&&t.setState({loading:!1})})),t.suggestionsRequest=o}))}},{key:"handleOnChange",value:function(e){(0,this.props.onChange)(this.getValuesForLabels(e))}},{key:"getTokens",value:function(){var e=this.props.tokens;return this.getLabelsForValues(e)}},{key:"render",value:function(){var e=this,t=this.props.label,n=void 0===t?"":t,o=this.state,c=o.suggestions,a=o.loading;return Object(i.createElement)("div",{className:"autocomplete-tokenfield"},Object(i.createElement)(l.FormTokenField,{value:this.getTokens(),suggestions:c,onChange:function(t){return e.handleOnChange(t)},onInputChange:function(t){return e.debouncedUpdateSuggestions(t)},label:n}),a&&Object(i.createElement)(l.Spinner,null))}}]),t}(i.Component)),V=function(e){function t(){var e,n;h()(this,t);for(var o=arguments.length,c=new Array(o),a=0;a<o;a++)c[a]=arguments[a];return n=m()(this,(e=O()(t)).call.apply(e,[this].concat(c))),E()(j()(n),"state",{showAdvancedFilters:!1}),E()(j()(n),"fetchPostSuggestions",(function(e){return P()({path:Object(A.addQueryArgs)("/wp/v2/search",{search:e,per_page:20,_fields:"id,title",type:"post"})}).then((function(e){return e.map((function(e){return{value:e.id,label:Object(T.decodeEntities)(e.title)||Object(r.__)("(no title)","newspack-blocks")}}))}))})),E()(j()(n),"fetchSavedPosts",(function(e){return P()({path:Object(A.addQueryArgs)("/wp/v2/posts",{per_page:100,include:e.join(","),_fields:"id,title"})}).then((function(e){return e.map((function(e){return{value:e.id,label:Object(T.decodeEntities)(e.title.rendered)||Object(r.__)("(no title)","newspack-blocks")}}))}))})),E()(j()(n),"fetchAuthorSuggestions",(function(e){return P()({path:Object(A.addQueryArgs)("/wp/v2/users",{search:e,per_page:20,_fields:"id,name"})}).then((function(e){return e.map((function(e){return{value:e.id,label:Object(T.decodeEntities)(e.name)||Object(r.__)("(no name)","newspack-blocks")}}))}))})),E()(j()(n),"fetchSavedAuthors",(function(e){return P()({path:Object(A.addQueryArgs)("/wp/v2/users",{per_page:100,include:e.join(","),_fields:"id,name"})}).then((function(e){return e.map((function(e){return{value:e.id,label:Object(T.decodeEntities)(e.name)||Object(r.__)("(no name)","newspack-blocks")}}))}))})),E()(j()(n),"fetchCategorySuggestions",(function(e){return P()({path:Object(A.addQueryArgs)("/wp/v2/categories",{search:e,per_page:20,_fields:"id,name",orderby:"count",order:"desc"})}).then((function(e){return e.map((function(e){return{value:e.id,label:Object(T.decodeEntities)(e.name)||Object(r.__)("(no title)","newspack-blocks")}}))}))})),E()(j()(n),"fetchSavedCategories",(function(e){return P()({path:Object(A.addQueryArgs)("/wp/v2/categories",{per_page:100,_fields:"id,name",include:e.join(",")})}).then((function(e){return e.map((function(e){return{value:e.id,label:Object(T.decodeEntities)(e.name)||Object(r.__)("(no title)","newspack-blocks")}}))}))})),E()(j()(n),"fetchTagSuggestions",(function(e){return P()({path:Object(A.addQueryArgs)("/wp/v2/tags",{search:e,per_page:20,_fields:"id,name",orderby:"count",order:"desc"})}).then((function(e){return e.map((function(e){return{value:e.id,label:Object(T.decodeEntities)(e.name)||Object(r.__)("(no title)","newspack-blocks")}}))}))})),E()(j()(n),"fetchSavedTags",(function(e){return P()({path:Object(A.addQueryArgs)("/wp/v2/tags",{per_page:100,_fields:"id,name",include:e.join(",")})}).then((function(e){return e.map((function(e){return{value:e.id,label:Object(T.decodeEntities)(e.name)||Object(r.__)("(no title)","newspack-blocks")}}))}))})),E()(j()(n),"render",(function(){var e=n.props,t=(e.numberOfItems,e.onNumberOfItemsChange,e.specificMode),o=e.onSpecificModeChange,c=e.specificPosts,a=e.onSpecificPostsChange,s=e.authors,u=e.onAuthorsChange,p=e.categories,b=e.onCategoriesChange,h=e.tags,f=e.onTagsChange,g=e.tagExclusions,d=e.onTagExclusionsChange,m=e.enableSpecific,w=n.state.showAdvancedFilters;return[m&&Object(i.createElement)(l.ToggleControl,{key:"specificMode",checked:t,onChange:o,label:Object(r.__)("Choose specific stories","newspack-blocks")}),t&&Object(i.createElement)(H,{key:"posts",tokens:c||[],onChange:a,fetchSuggestions:n.fetchPostSuggestions,fetchSavedInfo:n.fetchSavedPosts,label:Object(r.__)("Posts","newspack-blocks")}),!t&&Object(i.createElement)(l.QueryControls,C()({key:"queryControls"},n.props)),!t&&u&&Object(i.createElement)(H,{key:"authors",tokens:s||[],onChange:u,fetchSuggestions:n.fetchAuthorSuggestions,fetchSavedInfo:n.fetchSavedAuthors,label:Object(r.__)("Authors","newspack-blocks")}),!t&&b&&Object(i.createElement)(H,{key:"categories",tokens:p||[],onChange:b,fetchSuggestions:n.fetchCategorySuggestions,fetchSavedInfo:n.fetchSavedCategories,label:Object(r.__)("Categories","newspack-blocks")}),!t&&f&&Object(i.createElement)(H,{key:"tags",tokens:h||[],onChange:f,fetchSuggestions:n.fetchTagSuggestions,fetchSavedInfo:n.fetchSavedTags,label:Object(r.__)("Tags","newspack-blocks")}),!t&&d&&Object(i.createElement)("p",null,Object(i.createElement)(l.Button,{key:"toggle-advanced-filters",isLink:!0,onClick:function(){return n.setState({showAdvancedFilters:!w})}},w?Object(r.__)("Hide Advanced Filters","newspack-blocks"):Object(r.__)("Show Advanced Filters","newspack-blocks"))),!t&&d&&w&&Object(i.createElement)(H,{key:"tag-exclusion",tokens:g||[],onChange:d,fetchSuggestions:n.fetchTagSuggestions,fetchSavedInfo:n.fetchSavedTags,label:Object(r.__)("Excluded Tags","newspack-blocks")})]})),n}return v()(t,e),t}(i.Component);V.defaultProps={enableSpecific:!0,specificPosts:[],authors:[],categories:[],tags:[],tagExclusions:[]};var B=V,N=n(21),z=n.n(N),I=n(22),F=n.n(I),L=n(8),R=n(23),D=n(24),q=6,Q=Object(i.createElement)(l.SVG,{xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24"},Object(i.createElement)(l.Path,{d:"M0 0h24v24H0z",fill:"none"}),Object(i.createElement)(l.Path,{d:"M19 5H5c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 12H5V7h14v10z"})),G=Object(i.createElement)(l.SVG,{xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24"},Object(i.createElement)(l.Path,{d:"M0 0h24v24H0z",fill:"none"}),Object(i.createElement)(l.Path,{d:"M17 3H7c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H7V5h10v14z"})),U=Object(i.createElement)(l.SVG,{xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24"},Object(i.createElement)(l.Path,{d:"M0 0h24v24H0z",fill:"none"}),Object(i.createElement)(l.Path,{d:"M18 4H6c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 14H6V6h12v12z"})),W=Object(i.createElement)(l.SVG,{xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24"},Object(i.createElement)(l.Path,{d:"M0 0h24v24H0z",fill:"none"}),Object(i.createElement)(l.Path,{d:"M3 5v4h2V5h4V3H5c-1.1 0-2 .9-2 2zm2 10H3v4c0 1.1.9 2 2 2h4v-2H5v-4zm14 4h-4v2h4c1.1 0 2-.9 2-2v-4h-2v4zm0-16h-4v2h4v4h2V5c0-1.1-.9-2-2-2z"})),J=Object(i.createElement)(l.SVG,{xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24"},Object(i.createElement)(l.Path,{d:"M0 0h24v24H0z",fill:"none"}),Object(i.createElement)(l.Path,{d:"M4 4h7V2H4c-1.1 0-2 .9-2 2v7h2V4zm6 9l-4 5h12l-3-4-2.03 2.71L10 13zm7-4.5c0-.83-.67-1.5-1.5-1.5S14 7.67 14 8.5s.67 1.5 1.5 1.5S17 9.33 17 8.5zM20 2h-7v2h7v7h2V4c0-1.1-.9-2-2-2zm0 18h-7v2h7c1.1 0 2-.9 2-2v-7h-2v7zM4 13H2v7c0 1.1.9 2 2 2h7v-2H4v-7z"})),X=function(e){function t(){var e,n;h()(this,t);for(var o=arguments.length,c=new Array(o),a=0;a<o;a++)c[a]=arguments[a];return n=m()(this,(e=O()(t)).call.apply(e,[this].concat(c))),E()(j()(n),"renderPost",(function(e){var t=n.props.attributes,o=t.showImage,c=t.imageShape,a=t.mediaPosition,r=t.minHeight,s=t.showCaption,l=t.showExcerpt,u=t.showAuthor,p=t.showAvatar,b=t.showDate,h=t.showCategory,f=t.sectionHeader,g={minHeight:"behind"===a&&o&&e.newspack_featured_image_src&&r+"vh",paddingTop:"behind"===a&&o&&e.newspack_featured_image_src&&r/5+"vh"},d=(e.newspack_author_info.length,n.titleForPost(e));return Object(i.createElement)("article",{className:e.newspack_featured_image_src?"post-has-image":null,key:e.id,style:g},o&&e.newspack_featured_image_src&&Object(i.createElement)("figure",{className:"post-thumbnail",key:"thumbnail"},Object(i.createElement)("a",{href:"#"},"landscape"===c&&Object(i.createElement)("img",{src:e.newspack_featured_image_src.landscape}),"portrait"===c&&Object(i.createElement)("img",{src:e.newspack_featured_image_src.portrait}),"square"===c&&Object(i.createElement)("img",{src:e.newspack_featured_image_src.square}),"uncropped"===c&&Object(i.createElement)("img",{src:e.newspack_featured_image_src.uncropped})),s&&""!==e.newspack_featured_image_caption&&Object(i.createElement)("figcaption",null,e.newspack_featured_image_caption)),Object(i.createElement)("div",{className:"entry-wrapper"},h&&e.newspack_category_info.length&&Object(i.createElement)("div",{className:"cat-links"},Object(i.createElement)("a",{href:"#"},e.newspack_category_info)),L.RichText.isEmpty(f)?Object(i.createElement)("h2",{className:"entry-title",key:"title"},Object(i.createElement)("a",{href:"#"},d)):Object(i.createElement)("h3",{className:"entry-title",key:"title"},Object(i.createElement)("a",{href:"#"},d)),l&&Object(i.createElement)(i.RawHTML,{key:"excerpt",className:"excerpt-contain"},e.excerpt.rendered),Object(i.createElement)("div",{className:"entry-meta"},u&&p&&n.formatAvatars(e.newspack_author_info),u&&n.formatByline(e.newspack_author_info),b&&Object(i.createElement)("time",{className:"entry-date published",key:"pub-date"},F()(e.date_gmt).local().format("MMMM DD, Y")))))})),E()(j()(n),"titleForPost",(function(e){return e.title?"string"==typeof e.title?Object(T.decodeEntities)(e.title.trim()):"object"==typeof e.title&&e.title.rendered?Object(T.decodeEntities)(e.title.rendered.trim()):void 0:""})),E()(j()(n),"formatAvatars",(function(e){return e.map((function(e){return Object(i.createElement)("span",{className:"avatar author-avatar",key:e.id},Object(i.createElement)("a",{className:"url fn n",href:"#"},Object(i.createElement)(i.RawHTML,null,e.avatar)))}))})),E()(j()(n),"formatByline",(function(e){return Object(i.createElement)("span",{className:"byline"},Object(r.__)("by","newspack-blocks")," ",e.reduce((function(t,n,o){return[].concat(p()(t),[Object(i.createElement)("span",{className:"author vcard",key:n.id},Object(i.createElement)("a",{className:"url fn n",href:"#"},n.display_name)),o<e.length-2&&", ",e.length>1&&o===e.length-2&&Object(r.__)(" and ","newspack-blocks")])}),[]))})),E()(j()(n),"renderInspectorControls",(function(){var e=n.props,t=e.attributes,o=e.setAttributes,c=e.latestPosts,a=(e.isSelected,e.textColor),s=e.setTextColor,u=Array.isArray(c)&&c.length,p=t.authors,b=t.specificPosts,h=t.postsToShow,f=t.categories,g=(t.sectionHeader,t.columns),d=t.showImage,m=t.showCaption,w=t.imageScale,O=t.mobileStack,k=t.minHeight,j=t.moreButton,y=(t.moreButtonText,t.showExcerpt),v=t.typeScale,_=t.showDate,E=t.showAuthor,S=t.showAvatar,C=t.showCategory,x=t.postLayout,P=t.mediaPosition,A=t.specificMode,T=t.tags,M=t.tagExclusions,H=(t.url,[{value:1,label:Object(r.__)("Small","newspack-blocks"),shortName:Object(r.__)("S","newspack-blocks")},{value:2,label:Object(r.__)("Medium","newspack-blocks"),shortName:Object(r.__)("M","newspack-blocks")},{value:3,label:Object(r.__)("Large","newspack-blocks"),shortName:Object(r.__)("L","newspack-blocks")},{value:4,label:Object(r.__)("Extra Large","newspack-blocks"),shortName:Object(r.__)("XL","newspack-blocks")}]);return Object(i.createElement)(i.Fragment,null,Object(i.createElement)(l.PanelBody,{title:Object(r.__)("Display Settings","newspack-blocks"),initialOpen:!0},h&&Object(i.createElement)(B,{numberOfItems:h,onNumberOfItemsChange:function(e){return o({postsToShow:e})},specificMode:A,onSpecificModeChange:function(e){return o({specificMode:e})},specificPosts:b,onSpecificPostsChange:function(e){return o({specificPosts:e})},authors:p,onAuthorsChange:function(e){return o({authors:e})},categories:f,onCategoriesChange:function(e){return o({categories:e})},tags:T,onTagsChange:function(e){return o({tags:e})},tagExclusions:M,onTagExclusionsChange:function(e){return o({tagExclusions:e})}}),"grid"===x&&Object(i.createElement)(l.RangeControl,{label:Object(r.__)("Columns","newspack-blocks"),value:g,onChange:function(e){return o({columns:e})},min:2,max:u?Math.min(q,c.length):q,required:!0}),!A&&Object(i.createElement)(l.ToggleControl,{label:Object(r.__)('Show "More" Button',"newspack-blocks"),checked:j,onChange:function(){return o({moreButton:!j})},help:Object(r.__)("Only available for non-AMP requests.","newspack-blocks")})),Object(i.createElement)(l.PanelBody,{title:Object(r.__)("Featured Image Settings","newspack-blocks")},Object(i.createElement)(l.PanelRow,null,Object(i.createElement)(l.ToggleControl,{label:Object(r.__)("Show Featured Image","newspack-blocks"),checked:d,onChange:function(){return o({showImage:!d})}})),d&&Object(i.createElement)(l.PanelRow,null,Object(i.createElement)(l.ToggleControl,{label:Object(r.__)("Show Featured Image Caption","newspack-blocks"),checked:m,onChange:function(){return o({showCaption:!m})}})),d&&"top"!==P&&"behind"!==P&&Object(i.createElement)(i.Fragment,null,Object(i.createElement)(l.PanelRow,null,Object(i.createElement)(l.ToggleControl,{label:Object(r.__)("Stack on mobile","newspack-blocks"),checked:O,onChange:function(){return o({mobileStack:!O})}})),Object(i.createElement)(l.BaseControl,{label:Object(r.__)("Featured Image Size","newspack-blocks")},Object(i.createElement)(l.PanelRow,null,Object(i.createElement)(l.ButtonGroup,{"aria-label":Object(r.__)("Featured Image Size","newspack-blocks")},H.map((function(e){var t=w===e.value;return Object(i.createElement)(l.Button,{isLarge:!0,isPrimary:t,"aria-pressed":t,"aria-label":e.label,key:e.value,onClick:function(){return o({imageScale:e.value})}},e.shortName)})))))),d&&"behind"===P&&Object(i.createElement)(l.RangeControl,{label:Object(r.__)("Minimum height","newspack-blocks"),help:Object(r.__)("Sets a minimum height for the block, using a percentage of the screen's current height.","newspack-blocks"),value:k,onChange:function(e){return o({minHeight:e})},min:0,max:100,required:!0})),Object(i.createElement)(l.PanelBody,{title:Object(r.__)("Post Control Settings","newspack-blocks")},Object(i.createElement)(l.PanelRow,null,Object(i.createElement)(l.ToggleControl,{label:Object(r.__)("Show Excerpt","newspack-blocks"),checked:y,onChange:function(){return o({showExcerpt:!y})}})),Object(i.createElement)(l.RangeControl,{className:"type-scale-slider",label:Object(r.__)("Type Scale","newspack-blocks"),value:v,onChange:function(e){return o({typeScale:e})},min:1,max:10,beforeIcon:"editor-textcolor",afterIcon:"editor-textcolor",required:!0})),Object(i.createElement)(L.PanelColorSettings,{title:Object(r.__)("Color Settings","newspack-blocks"),initialOpen:!0,colorSettings:[{value:a.color,onChange:s,label:Object(r.__)("Text Color","newspack-blocks")}]}),Object(i.createElement)(l.PanelBody,{title:Object(r.__)("Post Meta Settings","newspack-blocks")},Object(i.createElement)(l.PanelRow,null,Object(i.createElement)(l.ToggleControl,{label:Object(r.__)("Show Date","newspack-blocks"),checked:_,onChange:function(){return o({showDate:!_})}})),Object(i.createElement)(l.PanelRow,null,Object(i.createElement)(l.ToggleControl,{label:Object(r.__)("Show Category","newspack-blocks"),checked:C,onChange:function(){return o({showCategory:!C})}})),Object(i.createElement)(l.PanelRow,null,Object(i.createElement)(l.ToggleControl,{label:Object(r.__)("Show Author","newspack-blocks"),checked:E,onChange:function(){return o({showAuthor:!E})}})),E&&Object(i.createElement)(l.PanelRow,null,Object(i.createElement)(l.ToggleControl,{label:Object(r.__)("Show Author Avatar","newspack-blocks"),checked:S,onChange:function(){return o({showAvatar:!S})}}))))})),n}return v()(t,e),g()(t,[{key:"render",value:function(){var e,t=this,n=this.props,o=n.attributes,c=n.className,a=n.setAttributes,s=n.isSelected,u=n.latestPosts,p=(n.hasPosts,n.textColor),b=(o.showExcerpt,o.showDate,o.showImage),h=o.imageShape,f=(o.showAuthor,o.showAvatar,o.postsToShow,o.postLayout),g=o.mediaPosition,d=o.moreButton,m=o.moreButtonText,w=o.columns,O=(o.categories,o.typeScale),k=o.imageScale,j=o.mobileStack,y=o.sectionHeader,v=o.showCaption,_=o.showCategory,S=o.specificMode,C=z()(c,(e={"is-grid":"grid"===f,"show-image":b},E()(e,"columns-".concat(w),"grid"===f),E()(e,"ts-".concat(O),"5"!==O),E()(e,"image-align".concat(g),b),E()(e,"is-".concat(k),"1"!==k&&b),E()(e,"mobile-stack",j),E()(e,"image-shape".concat(h),"landscape"!==h),E()(e,"has-text-color",""!==p.color),E()(e,"show-caption",v),E()(e,"show-category",_),E()(e,"wpnbha",!0),e)),x=[{icon:"list-view",title:Object(r.__)("List View","newspack-blocks"),onClick:function(){return a({postLayout:"list"})},isActive:"list"===f},{icon:"grid-view",title:Object(r.__)("Grid View","newspack-blocks"),onClick:function(){return a({postLayout:"grid"})},isActive:"grid"===f}],P=[{icon:"align-none",title:Object(r.__)("Show media on top","newspack-blocks"),isActive:"top"===g,onClick:function(){return a({mediaPosition:"top"})}},{icon:"align-pull-left",title:Object(r.__)("Show media on left","newspack-blocks"),isActive:"left"===g,onClick:function(){return a({mediaPosition:"left"})}},{icon:"align-pull-right",title:Object(r.__)("Show media on right","newspack-blocks"),isActive:"right"===g,onClick:function(){return a({mediaPosition:"right"})}},{icon:J,title:Object(r.__)("Show media behind","newspack-blocks"),isActive:"behind"===g,onClick:function(){return a({mediaPosition:"behind"})}}],A=[{icon:Q,title:Object(r.__)("Landscape Image Shape","newspack-blocks"),isActive:"landscape"===h,onClick:function(){return a({imageShape:"landscape"})}},{icon:G,title:Object(r.__)("portrait Image Shape","newspack-blocks"),isActive:"portrait"===h,onClick:function(){return a({imageShape:"portrait"})}},{icon:U,title:Object(r.__)("Square Image Shape","newspack-blocks"),isActive:"square"===h,onClick:function(){return a({imageShape:"square"})}},{icon:W,title:Object(r.__)("Uncropped","newspack-blocks"),isActive:"uncropped"===h,onClick:function(){return a({imageShape:"uncropped"})}}];return Object(i.createElement)(i.Fragment,null,Object(i.createElement)("div",{className:C,style:{color:p.color}},Object(i.createElement)("div",null,u&&(!L.RichText.isEmpty(y)||s)&&Object(i.createElement)(L.RichText,{onChange:function(e){return a({sectionHeader:e})},placeholder:Object(r.__)("Write header…","newspack-blocks"),value:y,tagName:"h2",className:"article-section-title"}),u&&!u.length&&Object(i.createElement)(l.Placeholder,null,Object(r.__)("Sorry, no posts were found.","newspack-blocks")),!u&&Object(i.createElement)(l.Placeholder,null,Object(i.createElement)(l.Spinner,null)),u&&u.map((function(e){return t.renderPost(e)})))),!S&&u&&d&&Object(i.createElement)("div",{className:"editor-styles-wrapper"},Object(i.createElement)("div",{className:"wp-block-button"},Object(i.createElement)(L.RichText,{placeholder:Object(r.__)("Load more posts","newspack-blocks"),value:m,onChange:function(e){return a({moreButtonText:e})},className:"wp-block-button__link",keepPlaceholderOnFocus:!0,allowedFormats:[]}))),Object(i.createElement)(L.BlockControls,null,Object(i.createElement)(l.Toolbar,{controls:x}),b&&Object(i.createElement)(l.Toolbar,{controls:P}),b&&Object(i.createElement)(l.Toolbar,{controls:A})),Object(i.createElement)(L.InspectorControls,null,this.renderInspectorControls()))}}]),t}(i.Component),Y=Object(D.compose)([Object(L.withColors)({textColor:"color"}),Object(R.withSelect)((function(e,t){var n=t.attributes,o=n.postsToShow,c=n.authors,a=n.categories,r=n.tags,s=n.tagExclusions,i=n.specificPosts,l=n.specificMode,u=e("core");u.getAuthors;return{latestPosts:(0,u.getEntityRecords)("postType","post",Object(M.pickBy)(l&&i&&i.length?{include:i,orderby:"include"}:{per_page:o,categories:a,author:c,tags:r,tags_exclude:s},(function(e){return!Object(M.isUndefined)(e)})))}}))])(X),K=(n(31),n(32),n(18)),Z=(K.name,K.attributes),$=K.category,ee={title:Object(r.__)("Homepage Posts","newspack-blocks"),icon:Object(i.createElement)(l.SVG,{xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24"},Object(i.createElement)(l.Path,{d:"M0 0h24v24H0z",fill:"none"}),Object(i.createElement)(l.Path,{d:"M4 6H2v14c0 1.1.9 2 2 2h14v-2H4V6zm16-4H8c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm0 14H8V4h12v12zM10 9h8v2h-8zm0 3h4v2h-4zm0-6h8v2h-8z"})),attributes:Z,category:$,keywords:[Object(r.__)("posts","newspack-blocks"),Object(r.__)("articles","newspack-blocks"),Object(r.__)("latest","newspack-blocks")],description:Object(r.__)("A block for displaying homepage posts.","newspack-blocks"),styles:[{name:"default",label:Object(r._x)("Default","block style","newspack-blocks"),isDefault:!0},{name:"borders",label:Object(r._x)("Borders","block style","newspack-blocks")}],supports:{html:!1,align:["wide","full"],default:""},edit:Y,save:function(){return null},transforms:{from:[{type:"block",blocks:["core/latest-posts"],transform:function(e){var t=e.displayPostContent,n=e.displayPostDate,o=e.postLayout,c=e.columns,r=e.postsToShow,i=e.categories;return Object(a.createBlock)(Object(s.applyFilters)("blocks.transforms_from_name","newspack-blocks/homepage-articles"),{showExcerpt:t,showDate:n,postLayout:o,columns:c,postsToShow:r,showAuthor:!1,categories:i?[i]:[]})}}],to:[{type:"block",blocks:["core/latest-posts"],transform:function(e){var t=e.showExcerpt,n=e.showDate,o=e.postLayout,c=e.columns,r=e.postsToShow,s=e.categories;return Object(a.createBlock)("core/latest-posts",{displayPostContent:t,displayPostDate:n,postLayout:o,columns:c,postsToShow:r,categories:s[0]||""})}}]}},te="a8c/blog-posts";Object(s.addFilter)("blocks.transforms_from_name","set-transformed-block-name",(function(e){return"newspack-blocks/homepage-articles"!==e?e:te})),Object(a.registerBlockType)(te,c()({},ee,{title:Object(r.__)("Blog Posts","full-site-editing"),category:"layout",supports:c()({},ee.supports,{multiple:!1})}))}]));
 
 
trunk/blog-posts-block/dist/editor.js.LICENSE DELETED
@@ -1,5 +0,0 @@
1
- /*!
2
- Copyright (c) 2017 Jed Watson.
3
- Licensed under the MIT License (MIT), see
4
- http://jedwatson.github.io/classnames
5
- */
 
 
 
 
 
trunk/blog-posts-block/dist/editor.rtl.css DELETED
@@ -1 +0,0 @@
1
- .autocomplete-tokenfield{position:relative}.autocomplete-tokenfield .components-spinner{position:absolute;top:2em;left:0}.type-scale-slider .dashicon{height:16px;width:16px}.type-scale-slider input+.dashicon{height:24px;margin-right:10px;margin-left:0;width:24px}.wpnbha .editor-rich-text{width:100%}.wpnbha .cat-links{font-size:.7em}.wpnbha span.avatar{display:inline-block;margin-left:.5em}.wpnbha span.avatar div{display:inline}.wpnbha .excerpt-contain p{margin:.5em 0}.wpnbha{margin-bottom:1em}.wpnbha article{margin-bottom:1.5em;word-break:break-word;overflow-wrap:break-word;position:relative}.wpnbha article:last-of-type{margin-bottom:0}.wpnbha .article-section-title{font-size:.8em;margin-bottom:.5em;width:100%}.wpnbha.is-grid>div{display:flex;flex-wrap:wrap;justify-content:space-between;padding:0;list-style:none}.wpnbha.is-grid article{flex-basis:100%}@media only screen and (min-width:782px){.wpnbha.is-grid article,.wpnbha.is-grid article:last-child{margin-bottom:1em}}@media only screen and (min-width:600px){.wpnbha.columns-3 article,.wpnbha.columns-6 article{flex-basis:calc(33.333% - 16px)}.wpnbha.columns-2 article,.wpnbha.columns-4 article,.wpnbha.columns-5 article{flex-basis:calc(50% - 16px)}.wpnbha.columns-5 article:last-of-type:nth-child(odd){flex-grow:1}}@media only screen and (min-width:782px){.wpnbha.columns-2 article{flex-basis:calc(50% - 16px)}.wpnbha.columns-3 article{flex-basis:calc(33.33333% - 16px)}.wpnbha.columns-4 article{flex-basis:calc(25% - 16px)}.wpnbha.columns-5 article{flex-basis:calc(20% - 16px)}.wpnbha.columns-6 article{flex-basis:calc(16.66667% - 16px)}}.wpnbha .post-thumbnail{margin:0}.wpnbha .post-thumbnail img{height:auto;width:100%}.wpnbha figcaption{font-size:.6em}.wpnbha .post-thumbnail{margin-bottom:.25em}.wpnbha .post-thumbnail figcaption{margin-bottom:.5em}.wpnbha.image-alignleft .post-has-image,.wpnbha.image-alignright .post-has-image{display:flex}.wpnbha.image-alignleft .post-has-image .post-thumbnail,.wpnbha.image-alignright .post-has-image .post-thumbnail{flex-basis:33%}.wpnbha.image-alignleft .post-has-image .entry-wrapper,.wpnbha.image-alignright .post-has-image .entry-wrapper{flex-basis:67%}.wpnbha.image-alignleft.mobile-stack .post-has-image,.wpnbha.image-alignright.mobile-stack .post-has-image{display:block}@media only screen and (min-width:600px){.wpnbha.image-alignleft.mobile-stack .post-has-image,.wpnbha.image-alignright.mobile-stack .post-has-image{display:flex}}@media only screen and (min-width:600px){.wpnbha.image-alignleft.is-4 .post-thumbnail,.wpnbha.image-alignright.is-4 .post-thumbnail{flex-basis:75%}.wpnbha.image-alignleft.is-4 .entry-wrapper,.wpnbha.image-alignright.is-4 .entry-wrapper{flex-basis:25%}.wpnbha.image-alignleft.is-3 .entry-wrapper,.wpnbha.image-alignleft.is-3 .post-thumbnail,.wpnbha.image-alignright.is-3 .entry-wrapper,.wpnbha.image-alignright.is-3 .post-thumbnail{flex-basis:50%}}.wpnbha.image-alignleft.is-1 .post-thumbnail,.wpnbha.image-alignright.is-1 .post-thumbnail{flex-basis:25%}.wpnbha.image-alignleft.is-1 .entry-wrapper,.wpnbha.image-alignright.is-1 .entry-wrapper{flex-basis:75%}.wpnbha.image-alignleft .post-thumbnail{margin-left:1em}.wpnbha.image-alignright .post-thumbnail{margin-right:1em}.wpnbha.image-alignright .entry-wrapper{order:-1}.wpnbha.mobile-stack.image-alignleft .post-thumbnail,.wpnbha.mobile-stack.image-alignright .post-thumbnail{margin-right:0;margin-left:0}@media only screen and (min-width:600px){.wpnbha.mobile-stack.image-alignleft .post-thumbnail{margin-left:1em}.wpnbha.mobile-stack.image-alignright .post-thumbnail{margin-right:1em}}.wpnbha .entry-title{margin:0 0 .25em}.wpnbha .entry-title a{color:inherit;text-decoration:none}.wpnbha .cat-links{font-size:.6em;font-weight:700;margin:0 0 .5em}.wpnbha .cat-links a{text-decoration:none}.wpnbha .cat-links a:hover{text-decoration:underline}.wpnbha .entry-meta{display:flex;flex-wrap:wrap;align-items:center;margin-top:.5em}.wpnbha .entry-meta .byline:not(:last-child){margin-left:1.5em}.wpnbha .entry-meta .updated:not(.published){display:none}.wpnbha .avatar{border-radius:100%;display:block;margin-left:.5em}.wpnbha p{margin:.5em 0}.wpnbha.has-text-color .article-section-title,.wpnbha.has-text-color .cat-links,.wpnbha.has-text-color .cat-links a,.wpnbha.has-text-color .cat-links a:visited,.wpnbha.has-text-color .entry-meta,.wpnbha.has-text-color .entry-meta .byline a,.wpnbha.has-text-color .entry-meta .byline a:visited,.wpnbha.has-text-color .entry-meta a,.wpnbha.has-text-color .entry-title,.wpnbha.has-text-color .entry-title a,.wpnbha.has-text-color .entry-title a:visited,.wpnbha.has-text-color figcaption{color:inherit}.wpnbha.has-text-color .entry-meta span:not(.avatar){opacity:.8}.wpnbha.image-alignbehind .post-has-image{display:flex;align-items:flex-end;position:relative}.wpnbha.image-alignbehind .post-has-image .post-thumbnail{bottom:0;right:0;margin:0;overflow:hidden;position:absolute;left:0;top:0}.wpnbha.image-alignbehind .post-has-image .post-thumbnail img{height:100%;-o-object-fit:cover;object-fit:cover;max-width:1000%;width:100%}.wpnbha.image-alignbehind .post-has-image .post-thumbnail figcaption{bottom:1em;-webkit-box-orient:vertical;color:hsla(0,0%,100%,.9);display:-webkit-box;font-style:italic;right:0;-webkit-line-clamp:1;margin:0;max-height:1.6em;overflow:hidden;padding:0 1em;position:absolute;left:0;text-align:left;text-overflow:ellipsis;z-index:2}.wpnbha.image-alignbehind .post-has-image .post-thumbnail:after{background:rgba(0,0,0,.5);bottom:0;content:"";right:0;position:absolute;left:0;top:0;z-index:1}.wpnbha.image-alignbehind .post-has-image .entry-wrapper{padding:2em;position:relative;z-index:2}.wpnbha.image-alignbehind .post-has-image .cat-links a,.wpnbha.image-alignbehind .post-has-image .entry-meta,.wpnbha.image-alignbehind .post-has-image .entry-meta .byline a,.wpnbha.image-alignbehind .post-has-image .entry-title a,.wpnbha.image-alignbehind .post-has-image .entry-wrapper{color:#fff}.wpnbha article .entry-title{font-size:1.2em}.wpnbha article .entry-meta{font-size:.8em}.wpnbha article .avatar{height:25px;width:25px}@media only screen and (min-width:782px){.wpnbha article .entry-title{font-size:1.6em}.wpnbha article .avatar{height:40px;width:40px}}.wpnbha.ts-8 .entry-title,.wpnbha.ts-9 .entry-title,.wpnbha.ts-10 .entry-title{line-height:1.1em}@media only screen and (min-width:782px){.wpnbha.ts-8 article .avatar,.wpnbha.ts-9 article .avatar,.wpnbha.ts-10 article .avatar{height:2.4em;width:2.4em}}.wpnbha.ts-10 article .entry-title{font-size:2.6em}@media only screen and (min-width:782px){.wpnbha.ts-10 article .entry-title{font-size:3.6em}}@media only screen and (min-width:1168px){.wpnbha.ts-10 article .entry-title{font-size:4.8em}}.wpnbha.ts-9 article .entry-title{font-size:2.4em}@media only screen and (min-width:782px){.wpnbha.ts-9 article .entry-title{font-size:3.4em}}@media only screen and (min-width:1168px){.wpnbha.ts-9 article .entry-title{font-size:4.2em}}.wpnbha.ts-8 article .entry-title{font-size:2.2em}@media only screen and (min-width:782px){.wpnbha.ts-8 article .entry-title{font-size:3em}}@media only screen and (min-width:1168px){.wpnbha.ts-8 article .entry-title{font-size:3.6em}}.wpnbha.ts-7 article .entry-title{font-size:2em}@media only screen and (min-width:782px){.wpnbha.ts-7 article .entry-title{font-size:2.4em}.wpnbha.ts-7 article .avatar{height:48px;width:48px}}@media only screen and (min-width:1168px){.wpnbha.ts-7 article .entry-title{font-size:3em}}.wpnbha.ts-6 article .entry-title{font-size:1.7em}@media only screen and (min-width:782px){.wpnbha.ts-6 article .entry-title{font-size:2em}.wpnbha.ts-6 article .avatar{height:44px;width:44px}}@media only screen and (min-width:1168px){.wpnbha.ts-6 article .entry-title{font-size:2.4em}}.wpnbha.ts-5 article .entry-title{font-size:1.4em}@media only screen and (min-width:782px){.wpnbha.ts-5 article .entry-title{font-size:1.8em}.wpnbha.ts-5 article .avatar{height:40px;width:40px}}@media only screen and (min-width:1168px){.wpnbha.ts-5 article .entry-title{font-size:2em}}.wpnbha.ts-3 article .entry-title{font-size:1em}.wpnbha.ts-3 article .entry-wrapper p{font-size:.8em}.wpnbha.ts-3 article .entry-meta{font-size:.7em}@media only screen and (min-width:782px){.wpnbha.ts-3 article .entry-title{font-size:1.2em}.wpnbha.ts-3 article .avatar{height:32px;width:32px}}.wpnbha.ts-2 article .entry-title{font-size:.8em}.wpnbha.ts-2 article .entry-meta,.wpnbha.ts-2 article .entry-wrapper p{font-size:.7em}@media only screen and (min-width:782px){.wpnbha.ts-2 article .entry-title{font-size:.9em}.wpnbha.ts-2 article .avatar{height:28px;width:28px}}.wpnbha.ts-1 article .entry-title,.wpnbha.ts-1 article .entry-wrapper p{font-size:.7em}.wpnbha.ts-1 article .entry-meta{font-size:.6em}@media only screen and (min-width:782px){.wpnbha.ts-1 article .avatar{height:24px;width:24px}}.wpnbha.is-style-borders article{border:solid rgba(0,0,0,.2);border-width:0 0 1px;margin-bottom:1em;padding-bottom:1em}.wpnbha.is-style-borders article:last-of-type{margin-bottom:0}.wpnbha.is-style-borders article:last-of-type:not(:first-of-type){border-bottom:0}@media only screen and (min-width:782px){.wpnbha.is-style-borders.columns-2 article{padding-left:32px}.wpnbha.is-style-borders.columns-3 article{padding-left:24px}.wpnbha.is-style-borders.columns-4 article{padding-left:21.33333px}.wpnbha.is-style-borders.columns-5 article{padding-left:20px}.wpnbha.is-style-borders.columns-6 article{padding-left:19.2px}.wpnbha.is-style-borders.is-grid article{border-width:0 0 0 1px}.wpnbha.is-style-borders.columns-1 article,.wpnbha.is-style-borders.columns-2 article:nth-of-type(2n),.wpnbha.is-style-borders.columns-3 article:nth-of-type(3n),.wpnbha.is-style-borders.columns-4 article:nth-of-type(4n),.wpnbha.is-style-borders.columns-5 article:nth-of-type(5n),.wpnbha.is-style-borders.columns-6 article:nth-of-type(6n),.wpnbha.is-style-borders.is-grid article:last-of-type{border:0}}
 
trunk/blog-posts-block/dist/view.asset.php DELETED
@@ -1 +0,0 @@
1
- <?php return array('dependencies' => array('wp-polyfill'), 'version' => '205364fc4e1fe4f20229ec21744b8df1');
 
trunk/blog-posts-block/dist/view.css DELETED
@@ -1 +0,0 @@
1
- .wpnbha{margin-bottom:1em}.wpnbha article{margin-bottom:1.5em;word-break:break-word;overflow-wrap:break-word;position:relative}.wpnbha article:last-of-type{margin-bottom:0}.wpnbha .article-section-title{font-size:.8em;margin-bottom:.5em;width:100%}.wpnbha.is-grid>div{display:flex;flex-wrap:wrap;justify-content:space-between;padding:0;list-style:none}.wpnbha.is-grid article{flex-basis:100%}@media only screen and (min-width:782px){.wpnbha.is-grid article,.wpnbha.is-grid article:last-child{margin-bottom:1em}}@media only screen and (min-width:600px){.wpnbha.columns-3 article,.wpnbha.columns-6 article{flex-basis:calc(33.333% - 16px)}.wpnbha.columns-2 article,.wpnbha.columns-4 article,.wpnbha.columns-5 article{flex-basis:calc(50% - 16px)}.wpnbha.columns-5 article:last-of-type:nth-child(odd){flex-grow:1}}@media only screen and (min-width:782px){.wpnbha.columns-2 article{flex-basis:calc(50% - 16px)}.wpnbha.columns-3 article{flex-basis:calc(33.33333% - 16px)}.wpnbha.columns-4 article{flex-basis:calc(25% - 16px)}.wpnbha.columns-5 article{flex-basis:calc(20% - 16px)}.wpnbha.columns-6 article{flex-basis:calc(16.66667% - 16px)}}.wpnbha .post-thumbnail{margin:0}.wpnbha .post-thumbnail img{height:auto;width:100%}.wpnbha figcaption{font-size:.6em}.wpnbha .post-thumbnail{margin-bottom:.25em}.wpnbha .post-thumbnail figcaption{margin-bottom:.5em}.wpnbha.image-alignleft .post-has-image,.wpnbha.image-alignright .post-has-image{display:flex}.wpnbha.image-alignleft .post-has-image .post-thumbnail,.wpnbha.image-alignright .post-has-image .post-thumbnail{flex-basis:33%}.wpnbha.image-alignleft .post-has-image .entry-wrapper,.wpnbha.image-alignright .post-has-image .entry-wrapper{flex-basis:67%}.wpnbha.image-alignleft.mobile-stack .post-has-image,.wpnbha.image-alignright.mobile-stack .post-has-image{display:block}@media only screen and (min-width:600px){.wpnbha.image-alignleft.mobile-stack .post-has-image,.wpnbha.image-alignright.mobile-stack .post-has-image{display:flex}}@media only screen and (min-width:600px){.wpnbha.image-alignleft.is-4 .post-thumbnail,.wpnbha.image-alignright.is-4 .post-thumbnail{flex-basis:75%}.wpnbha.image-alignleft.is-4 .entry-wrapper,.wpnbha.image-alignright.is-4 .entry-wrapper{flex-basis:25%}.wpnbha.image-alignleft.is-3 .entry-wrapper,.wpnbha.image-alignleft.is-3 .post-thumbnail,.wpnbha.image-alignright.is-3 .entry-wrapper,.wpnbha.image-alignright.is-3 .post-thumbnail{flex-basis:50%}}.wpnbha.image-alignleft.is-1 .post-thumbnail,.wpnbha.image-alignright.is-1 .post-thumbnail{flex-basis:25%}.wpnbha.image-alignleft.is-1 .entry-wrapper,.wpnbha.image-alignright.is-1 .entry-wrapper{flex-basis:75%}.wpnbha.image-alignleft .post-thumbnail{margin-right:1em}.wpnbha.image-alignright .post-thumbnail{margin-left:1em}.wpnbha.image-alignright .entry-wrapper{order:-1}.wpnbha.mobile-stack.image-alignleft .post-thumbnail,.wpnbha.mobile-stack.image-alignright .post-thumbnail{margin-left:0;margin-right:0}@media only screen and (min-width:600px){.wpnbha.mobile-stack.image-alignleft .post-thumbnail{margin-right:1em}.wpnbha.mobile-stack.image-alignright .post-thumbnail{margin-left:1em}}.wpnbha .entry-title{margin:0 0 .25em}.wpnbha .entry-title a{color:inherit;text-decoration:none}.wpnbha .cat-links{font-size:.6em;font-weight:700;margin:0 0 .5em}.wpnbha .cat-links a{text-decoration:none}.wpnbha .cat-links a:hover{text-decoration:underline}.wpnbha .entry-meta{display:flex;flex-wrap:wrap;align-items:center;margin-top:.5em}.wpnbha .entry-meta .byline:not(:last-child){margin-right:1.5em}.wpnbha .entry-meta .updated:not(.published){display:none}.wpnbha .avatar{border-radius:100%;display:block;margin-right:.5em}.wpnbha p{margin:.5em 0}.wpnbha.has-text-color .article-section-title,.wpnbha.has-text-color .cat-links,.wpnbha.has-text-color .cat-links a,.wpnbha.has-text-color .cat-links a:visited,.wpnbha.has-text-color .entry-meta,.wpnbha.has-text-color .entry-meta .byline a,.wpnbha.has-text-color .entry-meta .byline a:visited,.wpnbha.has-text-color .entry-meta a,.wpnbha.has-text-color .entry-title,.wpnbha.has-text-color .entry-title a,.wpnbha.has-text-color .entry-title a:visited,.wpnbha.has-text-color figcaption{color:inherit}.wpnbha.has-text-color .entry-meta span:not(.avatar){opacity:.8}.wpnbha.image-alignbehind .post-has-image{display:flex;align-items:flex-end;position:relative}.wpnbha.image-alignbehind .post-has-image .post-thumbnail{bottom:0;left:0;margin:0;overflow:hidden;position:absolute;right:0;top:0}.wpnbha.image-alignbehind .post-has-image .post-thumbnail img{height:100%;-o-object-fit:cover;object-fit:cover;max-width:1000%;width:100%}.wpnbha.image-alignbehind .post-has-image .post-thumbnail figcaption{bottom:1em;-webkit-box-orient:vertical;color:hsla(0,0%,100%,.9);display:-webkit-box;font-style:italic;left:0;-webkit-line-clamp:1;margin:0;max-height:1.6em;overflow:hidden;padding:0 1em;position:absolute;right:0;text-align:right;text-overflow:ellipsis;z-index:2}.wpnbha.image-alignbehind .post-has-image .post-thumbnail:after{background:rgba(0,0,0,.5);bottom:0;content:"";left:0;position:absolute;right:0;top:0;z-index:1}.wpnbha.image-alignbehind .post-has-image .entry-wrapper{padding:2em;position:relative;z-index:2}.wpnbha.image-alignbehind .post-has-image .cat-links a,.wpnbha.image-alignbehind .post-has-image .entry-meta,.wpnbha.image-alignbehind .post-has-image .entry-meta .byline a,.wpnbha.image-alignbehind .post-has-image .entry-title a,.wpnbha.image-alignbehind .post-has-image .entry-wrapper{color:#fff}.wpnbha article .entry-title{font-size:1.2em}.wpnbha article .entry-meta{font-size:.8em}.wpnbha article .avatar{height:25px;width:25px}@media only screen and (min-width:782px){.wpnbha article .entry-title{font-size:1.6em}.wpnbha article .avatar{height:40px;width:40px}}.wpnbha.ts-8 .entry-title,.wpnbha.ts-9 .entry-title,.wpnbha.ts-10 .entry-title{line-height:1.1em}@media only screen and (min-width:782px){.wpnbha.ts-8 article .avatar,.wpnbha.ts-9 article .avatar,.wpnbha.ts-10 article .avatar{height:2.4em;width:2.4em}}.wpnbha.ts-10 article .entry-title{font-size:2.6em}@media only screen and (min-width:782px){.wpnbha.ts-10 article .entry-title{font-size:3.6em}}@media only screen and (min-width:1168px){.wpnbha.ts-10 article .entry-title{font-size:4.8em}}.wpnbha.ts-9 article .entry-title{font-size:2.4em}@media only screen and (min-width:782px){.wpnbha.ts-9 article .entry-title{font-size:3.4em}}@media only screen and (min-width:1168px){.wpnbha.ts-9 article .entry-title{font-size:4.2em}}.wpnbha.ts-8 article .entry-title{font-size:2.2em}@media only screen and (min-width:782px){.wpnbha.ts-8 article .entry-title{font-size:3em}}@media only screen and (min-width:1168px){.wpnbha.ts-8 article .entry-title{font-size:3.6em}}.wpnbha.ts-7 article .entry-title{font-size:2em}@media only screen and (min-width:782px){.wpnbha.ts-7 article .entry-title{font-size:2.4em}.wpnbha.ts-7 article .avatar{height:48px;width:48px}}@media only screen and (min-width:1168px){.wpnbha.ts-7 article .entry-title{font-size:3em}}.wpnbha.ts-6 article .entry-title{font-size:1.7em}@media only screen and (min-width:782px){.wpnbha.ts-6 article .entry-title{font-size:2em}.wpnbha.ts-6 article .avatar{height:44px;width:44px}}@media only screen and (min-width:1168px){.wpnbha.ts-6 article .entry-title{font-size:2.4em}}.wpnbha.ts-5 article .entry-title{font-size:1.4em}@media only screen and (min-width:782px){.wpnbha.ts-5 article .entry-title{font-size:1.8em}.wpnbha.ts-5 article .avatar{height:40px;width:40px}}@media only screen and (min-width:1168px){.wpnbha.ts-5 article .entry-title{font-size:2em}}.wpnbha.ts-3 article .entry-title{font-size:1em}.wpnbha.ts-3 article .entry-wrapper p{font-size:.8em}.wpnbha.ts-3 article .entry-meta{font-size:.7em}@media only screen and (min-width:782px){.wpnbha.ts-3 article .entry-title{font-size:1.2em}.wpnbha.ts-3 article .avatar{height:32px;width:32px}}.wpnbha.ts-2 article .entry-title{font-size:.8em}.wpnbha.ts-2 article .entry-meta,.wpnbha.ts-2 article .entry-wrapper p{font-size:.7em}@media only screen and (min-width:782px){.wpnbha.ts-2 article .entry-title{font-size:.9em}.wpnbha.ts-2 article .avatar{height:28px;width:28px}}.wpnbha.ts-1 article .entry-title,.wpnbha.ts-1 article .entry-wrapper p{font-size:.7em}.wpnbha.ts-1 article .entry-meta{font-size:.6em}@media only screen and (min-width:782px){.wpnbha.ts-1 article .avatar{height:24px;width:24px}}.wpnbha.is-style-borders article{border:solid rgba(0,0,0,.2);border-width:0 0 1px;margin-bottom:1em;padding-bottom:1em}.wpnbha.is-style-borders article:last-of-type{margin-bottom:0}.wpnbha.is-style-borders article:last-of-type:not(:first-of-type){border-bottom:0}@media only screen and (min-width:782px){.wpnbha.is-style-borders.columns-2 article{padding-right:32px}.wpnbha.is-style-borders.columns-3 article{padding-right:24px}.wpnbha.is-style-borders.columns-4 article{padding-right:21.33333px}.wpnbha.is-style-borders.columns-5 article{padding-right:20px}.wpnbha.is-style-borders.columns-6 article{padding-right:19.2px}.wpnbha.is-style-borders.is-grid article{border-width:0 1px 0 0}.wpnbha.is-style-borders.columns-1 article,.wpnbha.is-style-borders.columns-2 article:nth-of-type(2n),.wpnbha.is-style-borders.columns-3 article:nth-of-type(3n),.wpnbha.is-style-borders.columns-4 article:nth-of-type(4n),.wpnbha.is-style-borders.columns-5 article:nth-of-type(5n),.wpnbha.is-style-borders.columns-6 article:nth-of-type(6n),.wpnbha.is-style-borders.is-grid article:last-of-type{border:0}}
 
trunk/blog-posts-block/dist/view.js DELETED
@@ -1 +0,0 @@
1
- !function(t,e){for(var r in e)t[r]=e[r]}(window,function(t){var e={};function r(n){if(e[n])return e[n].exports;var o=e[n]={i:n,l:!1,exports:{}};return t[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}return r.m=t,r.c=e,r.d=function(t,e,n){r.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},r.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},r.t=function(t,e){if(1&e&&(t=r(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var o in t)r.d(n,o,function(e){return t[e]}.bind(null,o));return n},r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,"a",e),e},r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r.p="",r(r.s=5)}([function(t,e,r){var n=r(1),o=r(2),i=r(3);t.exports=function(t){return n(t)||o(t)||i()}},function(t,e){t.exports=function(t){if(Array.isArray(t)){for(var e=0,r=new Array(t.length);e<t.length;e++)r[e]=t[e];return r}}},function(t,e){t.exports=function(t){if(Symbol.iterator in Object(t)||"[object Arguments]"===Object.prototype.toString.call(t))return Array.from(t)}},function(t,e){t.exports=function(){throw new TypeError("Invalid attempt to spread non-iterable instance")}},function(t,e,r){},function(t,e,r){"use strict";r.r(e);var n=r(0),o=r.n(n),i=(r(4),"data-load-more-url"),u=3;function a(t){t.style.display="none",t.setAttribute("hidden","")}function c(t){t.style.display="",t.removeAttribute("hidden")}function l(t,e){return Object.prototype.hasOwnProperty.call(t,e)}document.querySelectorAll("[data-load-more-btn]").forEach((function(t){if(!t)return null;var e=function(t){var e=t.parentElement,r=e.querySelector("[data-posts-container]"),n=e.querySelector("[data-load-more-loading-text]"),f=e.querySelector("[data-load-more-error-text]"),s=!1,d=!1;return function(){if(s||d)return!1;s=!0,a(t),a(f),c(n);var e,p,y=new URL(t.getAttribute(i));function m(){s=!1,a(n),c(f),c(t)}y.searchParams.set("exclude_ids",(e=document.querySelectorAll("article[data-post-id]"),p=Array.from(e).map((function(t){return t.getAttribute("data-post-id")})),o()(new Set(p))).join(",")),function t(e,r){var n=new XMLHttpRequest;n.onreadystatechange=function(){if(4===n.readyState){if(n.status>=200&&n.status<300){var o=JSON.parse(n.responseText);return e.onSuccess(o)}return r?t(e,r-1):e.onError()}},n.open("GET",e.url),n.send()}({url:y.toString(),onSuccess:function(e){if(!function(t){var e=!1;t&&l(t,"items")&&Array.isArray(t.items)&&l(t,"next")&&"string"==typeof t.next&&(e=!0,!t.items.length||l(t.items[0],"html")&&"string"==typeof t.items[0].html||(e=!1));return e}(e))return m();if(e.items.length){var o=e.items.map((function(t){return t.html})).join("");r.insertAdjacentHTML("beforeend",o)}e.next&&(t.setAttribute(i,e.next),c(t));e.items.length&&e.next||(d=!0);s=!1,a(n)},onError:m},u)}}(t);t.addEventListener("click",e)}))}]));
 
trunk/blog-posts-block/dist/view.rtl.css DELETED
@@ -1 +0,0 @@
1
- .wpnbha{margin-bottom:1em}.wpnbha article{margin-bottom:1.5em;word-break:break-word;overflow-wrap:break-word;position:relative}.wpnbha article:last-of-type{margin-bottom:0}.wpnbha .article-section-title{font-size:.8em;margin-bottom:.5em;width:100%}.wpnbha.is-grid>div{display:flex;flex-wrap:wrap;justify-content:space-between;padding:0;list-style:none}.wpnbha.is-grid article{flex-basis:100%}@media only screen and (min-width:782px){.wpnbha.is-grid article,.wpnbha.is-grid article:last-child{margin-bottom:1em}}@media only screen and (min-width:600px){.wpnbha.columns-3 article,.wpnbha.columns-6 article{flex-basis:calc(33.333% - 16px)}.wpnbha.columns-2 article,.wpnbha.columns-4 article,.wpnbha.columns-5 article{flex-basis:calc(50% - 16px)}.wpnbha.columns-5 article:last-of-type:nth-child(odd){flex-grow:1}}@media only screen and (min-width:782px){.wpnbha.columns-2 article{flex-basis:calc(50% - 16px)}.wpnbha.columns-3 article{flex-basis:calc(33.33333% - 16px)}.wpnbha.columns-4 article{flex-basis:calc(25% - 16px)}.wpnbha.columns-5 article{flex-basis:calc(20% - 16px)}.wpnbha.columns-6 article{flex-basis:calc(16.66667% - 16px)}}.wpnbha .post-thumbnail{margin:0}.wpnbha .post-thumbnail img{height:auto;width:100%}.wpnbha figcaption{font-size:.6em}.wpnbha .post-thumbnail{margin-bottom:.25em}.wpnbha .post-thumbnail figcaption{margin-bottom:.5em}.wpnbha.image-alignleft .post-has-image,.wpnbha.image-alignright .post-has-image{display:flex}.wpnbha.image-alignleft .post-has-image .post-thumbnail,.wpnbha.image-alignright .post-has-image .post-thumbnail{flex-basis:33%}.wpnbha.image-alignleft .post-has-image .entry-wrapper,.wpnbha.image-alignright .post-has-image .entry-wrapper{flex-basis:67%}.wpnbha.image-alignleft.mobile-stack .post-has-image,.wpnbha.image-alignright.mobile-stack .post-has-image{display:block}@media only screen and (min-width:600px){.wpnbha.image-alignleft.mobile-stack .post-has-image,.wpnbha.image-alignright.mobile-stack .post-has-image{display:flex}}@media only screen and (min-width:600px){.wpnbha.image-alignleft.is-4 .post-thumbnail,.wpnbha.image-alignright.is-4 .post-thumbnail{flex-basis:75%}.wpnbha.image-alignleft.is-4 .entry-wrapper,.wpnbha.image-alignright.is-4 .entry-wrapper{flex-basis:25%}.wpnbha.image-alignleft.is-3 .entry-wrapper,.wpnbha.image-alignleft.is-3 .post-thumbnail,.wpnbha.image-alignright.is-3 .entry-wrapper,.wpnbha.image-alignright.is-3 .post-thumbnail{flex-basis:50%}}.wpnbha.image-alignleft.is-1 .post-thumbnail,.wpnbha.image-alignright.is-1 .post-thumbnail{flex-basis:25%}.wpnbha.image-alignleft.is-1 .entry-wrapper,.wpnbha.image-alignright.is-1 .entry-wrapper{flex-basis:75%}.wpnbha.image-alignleft .post-thumbnail{margin-left:1em}.wpnbha.image-alignright .post-thumbnail{margin-right:1em}.wpnbha.image-alignright .entry-wrapper{order:-1}.wpnbha.mobile-stack.image-alignleft .post-thumbnail,.wpnbha.mobile-stack.image-alignright .post-thumbnail{margin-right:0;margin-left:0}@media only screen and (min-width:600px){.wpnbha.mobile-stack.image-alignleft .post-thumbnail{margin-left:1em}.wpnbha.mobile-stack.image-alignright .post-thumbnail{margin-right:1em}}.wpnbha .entry-title{margin:0 0 .25em}.wpnbha .entry-title a{color:inherit;text-decoration:none}.wpnbha .cat-links{font-size:.6em;font-weight:700;margin:0 0 .5em}.wpnbha .cat-links a{text-decoration:none}.wpnbha .cat-links a:hover{text-decoration:underline}.wpnbha .entry-meta{display:flex;flex-wrap:wrap;align-items:center;margin-top:.5em}.wpnbha .entry-meta .byline:not(:last-child){margin-left:1.5em}.wpnbha .entry-meta .updated:not(.published){display:none}.wpnbha .avatar{border-radius:100%;display:block;margin-left:.5em}.wpnbha p{margin:.5em 0}.wpnbha.has-text-color .article-section-title,.wpnbha.has-text-color .cat-links,.wpnbha.has-text-color .cat-links a,.wpnbha.has-text-color .cat-links a:visited,.wpnbha.has-text-color .entry-meta,.wpnbha.has-text-color .entry-meta .byline a,.wpnbha.has-text-color .entry-meta .byline a:visited,.wpnbha.has-text-color .entry-meta a,.wpnbha.has-text-color .entry-title,.wpnbha.has-text-color .entry-title a,.wpnbha.has-text-color .entry-title a:visited,.wpnbha.has-text-color figcaption{color:inherit}.wpnbha.has-text-color .entry-meta span:not(.avatar){opacity:.8}.wpnbha.image-alignbehind .post-has-image{display:flex;align-items:flex-end;position:relative}.wpnbha.image-alignbehind .post-has-image .post-thumbnail{bottom:0;right:0;margin:0;overflow:hidden;position:absolute;left:0;top:0}.wpnbha.image-alignbehind .post-has-image .post-thumbnail img{height:100%;-o-object-fit:cover;object-fit:cover;max-width:1000%;width:100%}.wpnbha.image-alignbehind .post-has-image .post-thumbnail figcaption{bottom:1em;-webkit-box-orient:vertical;color:hsla(0,0%,100%,.9);display:-webkit-box;font-style:italic;right:0;-webkit-line-clamp:1;margin:0;max-height:1.6em;overflow:hidden;padding:0 1em;position:absolute;left:0;text-align:left;text-overflow:ellipsis;z-index:2}.wpnbha.image-alignbehind .post-has-image .post-thumbnail:after{background:rgba(0,0,0,.5);bottom:0;content:"";right:0;position:absolute;left:0;top:0;z-index:1}.wpnbha.image-alignbehind .post-has-image .entry-wrapper{padding:2em;position:relative;z-index:2}.wpnbha.image-alignbehind .post-has-image .cat-links a,.wpnbha.image-alignbehind .post-has-image .entry-meta,.wpnbha.image-alignbehind .post-has-image .entry-meta .byline a,.wpnbha.image-alignbehind .post-has-image .entry-title a,.wpnbha.image-alignbehind .post-has-image .entry-wrapper{color:#fff}.wpnbha article .entry-title{font-size:1.2em}.wpnbha article .entry-meta{font-size:.8em}.wpnbha article .avatar{height:25px;width:25px}@media only screen and (min-width:782px){.wpnbha article .entry-title{font-size:1.6em}.wpnbha article .avatar{height:40px;width:40px}}.wpnbha.ts-8 .entry-title,.wpnbha.ts-9 .entry-title,.wpnbha.ts-10 .entry-title{line-height:1.1em}@media only screen and (min-width:782px){.wpnbha.ts-8 article .avatar,.wpnbha.ts-9 article .avatar,.wpnbha.ts-10 article .avatar{height:2.4em;width:2.4em}}.wpnbha.ts-10 article .entry-title{font-size:2.6em}@media only screen and (min-width:782px){.wpnbha.ts-10 article .entry-title{font-size:3.6em}}@media only screen and (min-width:1168px){.wpnbha.ts-10 article .entry-title{font-size:4.8em}}.wpnbha.ts-9 article .entry-title{font-size:2.4em}@media only screen and (min-width:782px){.wpnbha.ts-9 article .entry-title{font-size:3.4em}}@media only screen and (min-width:1168px){.wpnbha.ts-9 article .entry-title{font-size:4.2em}}.wpnbha.ts-8 article .entry-title{font-size:2.2em}@media only screen and (min-width:782px){.wpnbha.ts-8 article .entry-title{font-size:3em}}@media only screen and (min-width:1168px){.wpnbha.ts-8 article .entry-title{font-size:3.6em}}.wpnbha.ts-7 article .entry-title{font-size:2em}@media only screen and (min-width:782px){.wpnbha.ts-7 article .entry-title{font-size:2.4em}.wpnbha.ts-7 article .avatar{height:48px;width:48px}}@media only screen and (min-width:1168px){.wpnbha.ts-7 article .entry-title{font-size:3em}}.wpnbha.ts-6 article .entry-title{font-size:1.7em}@media only screen and (min-width:782px){.wpnbha.ts-6 article .entry-title{font-size:2em}.wpnbha.ts-6 article .avatar{height:44px;width:44px}}@media only screen and (min-width:1168px){.wpnbha.ts-6 article .entry-title{font-size:2.4em}}.wpnbha.ts-5 article .entry-title{font-size:1.4em}@media only screen and (min-width:782px){.wpnbha.ts-5 article .entry-title{font-size:1.8em}.wpnbha.ts-5 article .avatar{height:40px;width:40px}}@media only screen and (min-width:1168px){.wpnbha.ts-5 article .entry-title{font-size:2em}}.wpnbha.ts-3 article .entry-title{font-size:1em}.wpnbha.ts-3 article .entry-wrapper p{font-size:.8em}.wpnbha.ts-3 article .entry-meta{font-size:.7em}@media only screen and (min-width:782px){.wpnbha.ts-3 article .entry-title{font-size:1.2em}.wpnbha.ts-3 article .avatar{height:32px;width:32px}}.wpnbha.ts-2 article .entry-title{font-size:.8em}.wpnbha.ts-2 article .entry-meta,.wpnbha.ts-2 article .entry-wrapper p{font-size:.7em}@media only screen and (min-width:782px){.wpnbha.ts-2 article .entry-title{font-size:.9em}.wpnbha.ts-2 article .avatar{height:28px;width:28px}}.wpnbha.ts-1 article .entry-title,.wpnbha.ts-1 article .entry-wrapper p{font-size:.7em}.wpnbha.ts-1 article .entry-meta{font-size:.6em}@media only screen and (min-width:782px){.wpnbha.ts-1 article .avatar{height:24px;width:24px}}.wpnbha.is-style-borders article{border:solid rgba(0,0,0,.2);border-width:0 0 1px;margin-bottom:1em;padding-bottom:1em}.wpnbha.is-style-borders article:last-of-type{margin-bottom:0}.wpnbha.is-style-borders article:last-of-type:not(:first-of-type){border-bottom:0}@media only screen and (min-width:782px){.wpnbha.is-style-borders.columns-2 article{padding-left:32px}.wpnbha.is-style-borders.columns-3 article{padding-left:24px}.wpnbha.is-style-borders.columns-4 article{padding-left:21.33333px}.wpnbha.is-style-borders.columns-5 article{padding-left:20px}.wpnbha.is-style-borders.columns-6 article{padding-left:19.2px}.wpnbha.is-style-borders.is-grid article{border-width:0 0 0 1px}.wpnbha.is-style-borders.columns-1 article,.wpnbha.is-style-borders.columns-2 article:nth-of-type(2n),.wpnbha.is-style-borders.columns-3 article:nth-of-type(3n),.wpnbha.is-style-borders.columns-4 article:nth-of-type(4n),.wpnbha.is-style-borders.columns-5 article:nth-of-type(5n),.wpnbha.is-style-borders.columns-6 article:nth-of-type(6n),.wpnbha.is-style-borders.is-grid article:last-of-type{border:0}}
 
trunk/blog-posts-block/editor.js DELETED
@@ -1,38 +0,0 @@
1
- /* eslint-disable import/no-extraneous-dependencies */
2
- /**
3
- * Internal dependencies
4
- */
5
- import { registerBlockType } from '@wordpress/blocks';
6
- import { __ } from '@wordpress/i18n';
7
- import { addFilter } from '@wordpress/hooks';
8
- /* eslint-enable import/no-extraneous-dependencies */
9
-
10
- /**
11
- * NHA dependencies
12
- */
13
- import { settings } from './newspack-homepage-articles/blocks/homepage-articles/index';
14
-
15
- /**
16
- * Block name in the A8C\FSE context.
17
- */
18
- const blockName = 'a8c/blog-posts';
19
-
20
- function setBlockTransformationName( name ) {
21
- return name !== 'newspack-blocks/homepage-articles' ? name : blockName;
22
- }
23
-
24
- addFilter(
25
- 'blocks.transforms_from_name',
26
- 'set-transformed-block-name',
27
- setBlockTransformationName
28
- );
29
-
30
- registerBlockType( blockName, {
31
- ...settings,
32
- title: __( 'Blog Posts', 'full-site-editing' ),
33
- category: 'layout',
34
- supports: {
35
- ...settings.supports,
36
- multiple: false,
37
- },
38
- } );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/blog-posts-block/index.php DELETED
@@ -1,92 +0,0 @@
1
- <?php
2
- /**
3
- * Blog posts file.
4
- *
5
- * @package A8C\FSE
6
- */
7
-
8
- namespace A8C\FSE;
9
-
10
- define( 'NEWSPACK_BLOCKS__BLOCKS_DIRECTORY', 'dist/' );
11
- define( 'NEWSPACK_BLOCKS__PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
12
- define( 'NEWSPACK_BLOCKS__VERSION', '1.0.0-alpha.20' );
13
-
14
- /**
15
- * Filters block name.
16
- *
17
- * @param string $name Block name.
18
- * @return string
19
- */
20
- function blog_posts_block_name( $name ) {
21
- if ( 'newspack-blocks/homepage-articles' === $name ) {
22
- return 'a8c/blog-posts';
23
- }
24
- return $name;
25
- }
26
- add_filter( 'newspack_blocks_block_name', __NAMESPACE__ . '\blog_posts_block_name' );
27
-
28
- /**
29
- * Filters block arguments for `register_block_type()`.
30
- *
31
- * @param array $args Arguments to `register_block_type()`.
32
- * @param string $name Block name.
33
- * @return array
34
- */
35
- function blog_posts_block_args( $args, $name ) {
36
- if ( 'homepage-articles' !== $name ) {
37
- return $args;
38
- }
39
-
40
- // Editor script.
41
- $script_data = require NEWSPACK_BLOCKS__BLOCKS_DIRECTORY . 'editor.asset.php';
42
- wp_register_script(
43
- 'blog-posts-block-editor',
44
- plugins_url( NEWSPACK_BLOCKS__BLOCKS_DIRECTORY . 'editor.js', __FILE__ ),
45
- $script_data['dependencies'],
46
- $script_data['version'],
47
- true
48
- );
49
-
50
- // Editor style.
51
- $editor_style = plugins_url( NEWSPACK_BLOCKS__BLOCKS_DIRECTORY . 'editor.css', __FILE__ );
52
- wp_register_style( 'blog-posts-block-editor', $editor_style, array(), NEWSPACK_BLOCKS__VERSION );
53
-
54
- // View script.
55
- $script_data = require NEWSPACK_BLOCKS__BLOCKS_DIRECTORY . 'view.asset.php';
56
- wp_register_script(
57
- 'blog-posts-block-view',
58
- plugins_url( NEWSPACK_BLOCKS__BLOCKS_DIRECTORY . 'view.js', __FILE__ ),
59
- $script_data['dependencies'],
60
- $script_data['version'],
61
- true
62
- );
63
-
64
- // View style.
65
- $editor_style = plugins_url( NEWSPACK_BLOCKS__BLOCKS_DIRECTORY . 'view.css', __FILE__ );
66
- wp_register_style( 'blog-posts-block-view', $editor_style, array(), NEWSPACK_BLOCKS__VERSION );
67
-
68
- $args['editor_script'] = 'blog-posts-block-editor';
69
- $args['editor_style'] = 'blog-posts-block-editor';
70
- $args['script'] = 'blog-posts-block-view';
71
- $args['style'] = 'blog-posts-block-view';
72
-
73
- return $args;
74
- }
75
- add_filter( 'newspack_blocks_block_args', __NAMESPACE__ . '\blog_posts_block_args', 10, 2 );
76
-
77
- require_once __DIR__ . '/newspack-homepage-articles/class-newspack-blocks.php';
78
- require_once __DIR__ . '/newspack-homepage-articles/class-newspack-blocks-api.php';
79
-
80
- require_once __DIR__ . '/newspack-homepage-articles/blocks/homepage-articles/view.php';
81
-
82
- // REST Controller for Articles Block.
83
- require_once NEWSPACK_BLOCKS__PLUGIN_DIR . 'newspack-homepage-articles/blocks/homepage-articles/class-wp-rest-newspack-articles-controller.php';
84
-
85
- /**
86
- * Registers Articles block routes.
87
- */
88
- function register_rest_routes() {
89
- $articles_controller = new \WP_REST_Newspack_Articles_Controller();
90
- $articles_controller->register_routes();
91
- }
92
- add_action( 'rest_api_init', __NAMESPACE__ . '\register_rest_routes' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/blog-posts-block/newspack-homepage-articles/README.md DELETED
@@ -1,5 +0,0 @@
1
- # Newspack Homepage Articles
2
-
3
- This folder is synchronized from [Newspack Blocks repository](https://github.com/automattic/newspack-blocks) where the original code lives.
4
-
5
- Please don't make any changes to these files directly but rather open a PR in the original repository and once landed there, use the sync script.
 
 
 
 
 
trunk/blog-posts-block/newspack-homepage-articles/blocks/homepage-articles/block.json DELETED
@@ -1,127 +0,0 @@
1
- {
2
- "name": "homepage-articles",
3
- "category": "newspack",
4
- "attributes": {
5
- "className": {
6
- "type": "string",
7
- "default": ""
8
- },
9
- "showExcerpt": {
10
- "type": "boolean",
11
- "default": true
12
- },
13
- "showDate": {
14
- "type": "boolean",
15
- "default": true
16
- },
17
- "showImage": {
18
- "type": "boolean",
19
- "default": true
20
- },
21
- "showCaption": {
22
- "type": "boolean",
23
- "default": false
24
- },
25
- "imageShape": {
26
- "type": "string",
27
- "default": "landscape"
28
- },
29
- "minHeight": {
30
- "type": "integer",
31
- "default": 0
32
- },
33
- "moreButton": {
34
- "type": "boolean",
35
- "default": false
36
- },
37
- "moreButtonText": {
38
- "type": "string",
39
- "default": ""
40
- },
41
- "showAuthor": {
42
- "type": "boolean",
43
- "default": true
44
- },
45
- "showAvatar": {
46
- "type": "boolean",
47
- "default": true
48
- },
49
- "showCategory": {
50
- "type": "boolean",
51
- "default": false
52
- },
53
- "postLayout": {
54
- "type": "string",
55
- "default": "list"
56
- },
57
- "columns": {
58
- "type": "integer",
59
- "default": 3
60
- },
61
- "postsToShow": {
62
- "type": "integer",
63
- "default": 3
64
- },
65
- "mediaPosition": {
66
- "type": "string",
67
- "default": "top"
68
- },
69
- "authors": {
70
- "type": "array",
71
- "default": [],
72
- "items": { "type": "integer" }
73
- },
74
- "categories": {
75
- "type": "array",
76
- "default": [],
77
- "items": { "type": "integer" }
78
- },
79
- "tags": {
80
- "type": "array",
81
- "default": [],
82
- "items": { "type": "integer" }
83
- },
84
- "tagExclusions": {
85
- "type": "array",
86
- "default": [],
87
- "items": { "type": "integer" }
88
- },
89
- "specificPosts": {
90
- "type": "array",
91
- "default": [],
92
- "items": { "type": "integer" }
93
- },
94
- "typeScale": {
95
- "type": "integer",
96
- "default": 4
97
- },
98
- "imageScale": {
99
- "type": "integer",
100
- "default": 3
101
- },
102
- "mobileStack": {
103
- "type": "boolean",
104
- "default": false
105
- },
106
- "sectionHeader": {
107
- "type": "string",
108
- "default": ""
109
- },
110
- "specificMode": {
111
- "type": "boolean",
112
- "default": false
113
- },
114
- "textColor": {
115
- "type": "string",
116
- "default": ""
117
- },
118
- "customTextColor": {
119
- "type": "string",
120
- "default": ""
121
- },
122
- "singleMode": {
123
- "type": "boolean",
124
- "default": false
125
- }
126
- }
127
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/blog-posts-block/newspack-homepage-articles/blocks/homepage-articles/class-wp-rest-newspack-articles-controller.php DELETED
@@ -1,143 +0,0 @@
1
- <?php
2
- /**
3
- * WP_REST_Newspack_Articles_Controller file.
4
- *
5
- * @package WordPress
6
- */
7
-
8
- /**
9
- * Class WP_REST_Newspack_Articles_Controller.
10
- */
11
- class WP_REST_Newspack_Articles_Controller extends WP_REST_Controller {
12
-
13
- /**
14
- * Attribute schema.
15
- *
16
- * @var array
17
- */
18
- public $attribute_schema;
19
-
20
- /**
21
- * Constructs the controller.
22
- *
23
- * @access public
24
- */
25
- public function __construct() {
26
- $this->namespace = 'newspack-blocks/v1';
27
- $this->rest_base = 'articles';
28
- }
29
-
30
- /**
31
- * Registers the necessary REST API routes.
32
- *
33
- * @access public
34
- */
35
- public function register_routes() {
36
- register_rest_route(
37
- $this->namespace,
38
- '/' . $this->rest_base,
39
- array(
40
- array(
41
- 'methods' => WP_REST_Server::READABLE,
42
- 'callback' => array( $this, 'get_items' ),
43
- 'args' => $this->get_attribute_schema(),
44
- 'permission_callback' => '__return_true',
45
- ),
46
- )
47
- );
48
- }
49
-
50
- /**
51
- * Returns a list of rendered posts.
52
- *
53
- * @param WP_REST_Request $request Request object.
54
- * @return WP_REST_Response
55
- */
56
- public function get_items( $request ) {
57
- $page = $request->get_param( 'page' ) ?? 1;
58
- $exclude_ids = $request->get_param( 'exclude_ids' ) ?? array();
59
- $next_page = $page + 1;
60
- $attributes = wp_parse_args(
61
- $request->get_params() ?? array(),
62
- wp_list_pluck( $this->get_attribute_schema(), 'default' )
63
- );
64
-
65
- $article_query_args = Newspack_Blocks::build_articles_query( $attributes );
66
-
67
- $query = array_merge(
68
- $article_query_args,
69
- array(
70
- 'post__not_in' => $exclude_ids,
71
- )
72
- );
73
-
74
- // Run Query.
75
- $article_query = new WP_Query( $query );
76
-
77
- // Defaults.
78
- $items = array();
79
- $next_url = '';
80
-
81
- // The Loop.
82
- while ( $article_query->have_posts() ) {
83
- $article_query->the_post();
84
- $items[]['html'] = Newspack_Blocks::template_inc(
85
- __DIR__ . '/templates/article.php',
86
- array(
87
- 'attributes' => $attributes,
88
- )
89
- );
90
- }
91
-
92
- // Provide next URL if there are more pages.
93
- if ( $next_page <= $article_query->max_num_pages ) {
94
- $next_url = add_query_arg(
95
- array_merge(
96
- array_map(
97
- function( $attribute ) {
98
- return false === $attribute ? '0' : $attribute;
99
- },
100
- $attributes
101
- ),
102
- array( 'page' => $next_page ) // phpcs:ignore PHPCompatibility.Syntax.NewShortArray.Found
103
- ),
104
- rest_url( '/newspack-blocks/v1/articles' )
105
- );
106
- }
107
-
108
- return rest_ensure_response(
109
- array(
110
- 'items' => $items,
111
- 'next' => $next_url,
112
- )
113
- );
114
- }
115
-
116
- /**
117
- * Sets up and returns attribute schema.
118
- *
119
- * @return array
120
- */
121
- public function get_attribute_schema() {
122
- if ( empty( $this->attribute_schema ) ) {
123
- $block_json = json_decode(
124
- file_get_contents( __DIR__ . '/block.json' ), // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
125
- true
126
- );
127
-
128
- $this->attribute_schema = array_merge(
129
- $block_json['attributes'],
130
- array(
131
- 'exclude_ids' => array(
132
- 'type' => 'array',
133
- 'default' => array(),
134
- 'items' => array(
135
- 'type' => 'integer',
136
- ),
137
- ),
138
- )
139
- );
140
- }
141
- return $this->attribute_schema;
142
- }
143
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/blog-posts-block/newspack-homepage-articles/blocks/homepage-articles/edit.js DELETED
@@ -1,677 +0,0 @@
1
- /**
2
- * Internal dependencies
3
- */
4
- import QueryControls from '../../components/query-controls';
5
-
6
- /**
7
- * External dependencies
8
- */
9
- import classNames from 'classnames';
10
- import { isUndefined, pickBy } from 'lodash';
11
- import moment from 'moment';
12
-
13
- /**
14
- * WordPress dependencies
15
- */
16
- import { __ } from '@wordpress/i18n';
17
- import { Component, Fragment, RawHTML } from '@wordpress/element';
18
- import {
19
- BlockControls,
20
- InspectorControls,
21
- PanelColorSettings,
22
- RichText,
23
- withColors,
24
- } from '@wordpress/block-editor';
25
- import {
26
- Button,
27
- ButtonGroup,
28
- PanelBody,
29
- PanelRow,
30
- RangeControl,
31
- Toolbar,
32
- ToggleControl,
33
- Dashicon,
34
- Placeholder,
35
- Spinner,
36
- BaseControl,
37
- Path,
38
- SVG,
39
- } from '@wordpress/components';
40
- import { withSelect } from '@wordpress/data';
41
- import { compose } from '@wordpress/compose';
42
- import { addQueryArgs } from '@wordpress/url';
43
- import { decodeEntities } from '@wordpress/html-entities';
44
-
45
- /**
46
- * Module Constants
47
- */
48
- const MAX_POSTS_COLUMNS = 6;
49
-
50
- /* From https://material.io/tools/icons */
51
- const landscapeIcon = (
52
- <SVG xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
53
- <Path d="M0 0h24v24H0z" fill="none" />
54
- <Path d="M19 5H5c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 12H5V7h14v10z" />
55
- </SVG>
56
- );
57
-
58
- const portraitIcon = (
59
- <SVG xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
60
- <Path d="M0 0h24v24H0z" fill="none" />
61
- <Path d="M17 3H7c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H7V5h10v14z" />
62
- </SVG>
63
- );
64
-
65
- const squareIcon = (
66
- <SVG xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
67
- <Path d="M0 0h24v24H0z" fill="none" />
68
- <Path d="M18 4H6c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 14H6V6h12v12z" />
69
- </SVG>
70
- );
71
-
72
- const uncroppedIcon = (
73
- <SVG xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
74
- <Path d="M0 0h24v24H0z" fill="none" />
75
- <Path d="M3 5v4h2V5h4V3H5c-1.1 0-2 .9-2 2zm2 10H3v4c0 1.1.9 2 2 2h4v-2H5v-4zm14 4h-4v2h4c1.1 0 2-.9 2-2v-4h-2v4zm0-16h-4v2h4v4h2V5c0-1.1-.9-2-2-2z" />
76
- </SVG>
77
- );
78
-
79
- const coverIcon = (
80
- <SVG xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
81
- <Path d="M0 0h24v24H0z" fill="none" />
82
- <Path d="M4 4h7V2H4c-1.1 0-2 .9-2 2v7h2V4zm6 9l-4 5h12l-3-4-2.03 2.71L10 13zm7-4.5c0-.83-.67-1.5-1.5-1.5S14 7.67 14 8.5s.67 1.5 1.5 1.5S17 9.33 17 8.5zM20 2h-7v2h7v7h2V4c0-1.1-.9-2-2-2zm0 18h-7v2h7c1.1 0 2-.9 2-2v-7h-2v7zM4 13H2v7c0 1.1.9 2 2 2h7v-2H4v-7z" />
83
- </SVG>
84
- );
85
-
86
- class Edit extends Component {
87
- renderPost = post => {
88
- const { attributes } = this.props;
89
- const {
90
- showImage,
91
- imageShape,
92
- mediaPosition,
93
- minHeight,
94
- showCaption,
95
- showExcerpt,
96
- showAuthor,
97
- showAvatar,
98
- showDate,
99
- showCategory,
100
- sectionHeader,
101
- } = attributes;
102
-
103
- const styles = {
104
- minHeight:
105
- mediaPosition === 'behind' &&
106
- showImage &&
107
- post.newspack_featured_image_src &&
108
- minHeight + 'vh',
109
- paddingTop:
110
- mediaPosition === 'behind' &&
111
- showImage &&
112
- post.newspack_featured_image_src &&
113
- minHeight / 5 + 'vh',
114
- };
115
-
116
- const authorNumber = post.newspack_author_info.length;
117
- const postTitle = this.titleForPost( post );
118
- return (
119
- <article
120
- className={ post.newspack_featured_image_src ? 'post-has-image' : null }
121
- key={ post.id }
122
- style={ styles }
123
- >
124
- { showImage && post.newspack_featured_image_src && (
125
- <figure className="post-thumbnail" key="thumbnail">
126
- <a href="#">
127
- { imageShape === 'landscape' && (
128
- <img src={ post.newspack_featured_image_src.landscape } />
129
- ) }
130
- { imageShape === 'portrait' && (
131
- <img src={ post.newspack_featured_image_src.portrait } />
132
- ) }
133
- { imageShape === 'square' && <img src={ post.newspack_featured_image_src.square } /> }
134
-
135
- { imageShape === 'uncropped' && (
136
- <img src={ post.newspack_featured_image_src.uncropped } />
137
- ) }
138
- </a>
139
- { showCaption && '' !== post.newspack_featured_image_caption && (
140
- <figcaption>{ post.newspack_featured_image_caption }</figcaption>
141
- ) }
142
- </figure>
143
- ) }
144
-
145
- <div className="entry-wrapper">
146
- { showCategory && post.newspack_category_info.length && (
147
- <div className="cat-links">
148
- <a href="#">{ post.newspack_category_info }</a>
149
- </div>
150
- ) }
151
- { RichText.isEmpty( sectionHeader ) ? (
152
- <h2 className="entry-title" key="title">
153
- <a href="#">{ postTitle }</a>
154
- </h2>
155
- ) : (
156
- <h3 className="entry-title" key="title">
157
- <a href="#">{ postTitle }</a>
158
- </h3>
159
- ) }
160
- { showExcerpt && (
161
- <RawHTML key="excerpt" className="excerpt-contain">
162
- { post.excerpt.rendered }
163
- </RawHTML>
164
- ) }
165
- <div className="entry-meta">
166
- { showAuthor && showAvatar && this.formatAvatars( post.newspack_author_info ) }
167
- { showAuthor && this.formatByline( post.newspack_author_info ) }
168
- { showDate && (
169
- <time className="entry-date published" key="pub-date">
170
- { moment( post.date_gmt )
171
- .local()
172
- .format( 'MMMM DD, Y' ) }
173
- </time>
174
- ) }
175
- </div>
176
- </div>
177
- </article>
178
- );
179
- };
180
-
181
- titleForPost = post => {
182
- if ( ! post.title ) {
183
- return '';
184
- }
185
- if ( typeof post.title === 'string' ) {
186
- return decodeEntities( post.title.trim() );
187
- }
188
- if ( typeof post.title === 'object' && post.title.rendered ) {
189
- return decodeEntities( post.title.rendered.trim() );
190
- }
191
- };
192
-
193
- formatAvatars = authorInfo =>
194
- authorInfo.map( author => (
195
- <span className="avatar author-avatar" key={ author.id }>
196
- <a className="url fn n" href="#">
197
- <RawHTML>{ author.avatar }</RawHTML>
198
- </a>
199
- </span>
200
- ) );
201
-
202
- formatByline = authorInfo => (
203
- <span className="byline">
204
- { __( 'by', 'newspack-blocks' ) }{ ' ' }
205
- { authorInfo.reduce( ( accumulator, author, index ) => {
206
- return [
207
- ...accumulator,
208
- <span className="author vcard" key={ author.id }>
209
- <a className="url fn n" href="#">
210
- { author.display_name }
211
- </a>
212
- </span>,
213
- index < authorInfo.length - 2 && ', ',
214
- authorInfo.length > 1 &&
215
- index === authorInfo.length - 2 &&
216
- __( ' and ', 'newspack-blocks' ),
217
- ];
218
- }, [] ) }
219
- </span>
220
- );
221
-
222
- renderInspectorControls = () => {
223
- const {
224
- attributes,
225
- setAttributes,
226
- latestPosts,
227
- isSelected,
228
- textColor,
229
- setTextColor,
230
- } = this.props;
231
- const hasPosts = Array.isArray( latestPosts ) && latestPosts.length;
232
-
233
- const {
234
- authors,
235
- specificPosts,
236
- postsToShow,
237
- categories,
238
- sectionHeader,
239
- columns,
240
- showImage,
241
- showCaption,
242
- imageScale,
243
- mobileStack,
244
- minHeight,
245
- moreButton,
246
- moreButtonText,
247
- showExcerpt,
248
- typeScale,
249
- showDate,
250
- showAuthor,
251
- showAvatar,
252
- showCategory,
253
- postLayout,
254
- mediaPosition,
255
- specificMode,
256
- tags,
257
- tagExclusions,
258
- url,
259
- } = attributes;
260
-
261
- const imageSizeOptions = [
262
- {
263
- value: 1,
264
- label: /* translators: label for small size option */ __( 'Small', 'newspack-blocks' ),
265
- shortName: /* translators: abbreviation for small size */ __( 'S', 'newspack-blocks' ),
266
- },
267
- {
268
- value: 2,
269
- label: /* translators: label for medium size option */ __( 'Medium', 'newspack-blocks' ),
270
- shortName: /* translators: abbreviation for medium size */ __( 'M', 'newspack-blocks' ),
271
- },
272
- {
273
- value: 3,
274
- label: /* translators: label for large size option */ __( 'Large', 'newspack-blocks' ),
275
- shortName: /* translators: abbreviation for large size */ __( 'L', 'newspack-blocks' ),
276
- },
277
- {
278
- value: 4,
279
- label: /* translators: label for extra large size option */ __(
280
- 'Extra Large',
281
- 'newspack-blocks'
282
- ),
283
- shortName: /* translators: abbreviation for extra large size */ __(
284
- 'XL',
285
- 'newspack-blocks'
286
- ),
287
- },
288
- ];
289
-
290
- return (
291
- <Fragment>
292
- <PanelBody title={ __( 'Display Settings', 'newspack-blocks' ) } initialOpen={ true }>
293
- { postsToShow && (
294
- <QueryControls
295
- numberOfItems={ postsToShow }
296
- onNumberOfItemsChange={ value => setAttributes( { postsToShow: value } ) }
297
- specificMode={ specificMode }
298
- onSpecificModeChange={ value => setAttributes( { specificMode: value } ) }
299
- specificPosts={ specificPosts }
300
- onSpecificPostsChange={ value => setAttributes( { specificPosts: value } ) }
301
- authors={ authors }
302
- onAuthorsChange={ value => setAttributes( { authors: value } ) }
303
- categories={ categories }
304
- onCategoriesChange={ value => setAttributes( { categories: value } ) }
305
- tags={ tags }
306
- onTagsChange={ value => setAttributes( { tags: value } ) }
307
- tagExclusions={ tagExclusions }
308
- onTagExclusionsChange={ value => setAttributes( { tagExclusions: value } ) }
309
- />
310
- ) }
311
- { postLayout === 'grid' && (
312
- <RangeControl
313
- label={ __( 'Columns', 'newspack-blocks' ) }
314
- value={ columns }
315
- onChange={ value => setAttributes( { columns: value } ) }
316
- min={ 2 }
317
- max={
318
- ! hasPosts ? MAX_POSTS_COLUMNS : Math.min( MAX_POSTS_COLUMNS, latestPosts.length )
319
- }
320
- required
321
- />
322
- ) }
323
- { ! specificMode && (
324
- <ToggleControl
325
- label={ __( 'Show "More" Button', 'newspack-blocks' ) }
326
- checked={ moreButton }
327
- onChange={ () => setAttributes( { moreButton: ! moreButton } ) }
328
- help={ __( 'Only available for non-AMP requests.', 'newspack-blocks' ) }
329
- />
330
- ) }
331
- </PanelBody>
332
- <PanelBody title={ __( 'Featured Image Settings', 'newspack-blocks' ) }>
333
- <PanelRow>
334
- <ToggleControl
335
- label={ __( 'Show Featured Image', 'newspack-blocks' ) }
336
- checked={ showImage }
337
- onChange={ () => setAttributes( { showImage: ! showImage } ) }
338
- />
339
- </PanelRow>
340
-
341
- { showImage && (
342
- <PanelRow>
343
- <ToggleControl
344
- label={ __( 'Show Featured Image Caption', 'newspack-blocks' ) }
345
- checked={ showCaption }
346
- onChange={ () => setAttributes( { showCaption: ! showCaption } ) }
347
- />
348
- </PanelRow>
349
- ) }
350
-
351
- { showImage && mediaPosition !== 'top' && mediaPosition !== 'behind' && (
352
- <Fragment>
353
- <PanelRow>
354
- <ToggleControl
355
- label={ __( 'Stack on mobile', 'newspack-blocks' ) }
356
- checked={ mobileStack }
357
- onChange={ () => setAttributes( { mobileStack: ! mobileStack } ) }
358
- />
359
- </PanelRow>
360
- <BaseControl label={ __( 'Featured Image Size', 'newspack-blocks' ) }>
361
- <PanelRow>
362
- <ButtonGroup aria-label={ __( 'Featured Image Size', 'newspack-blocks' ) }>
363
- { imageSizeOptions.map( option => {
364
- const isCurrent = imageScale === option.value;
365
- return (
366
- <Button
367
- isLarge
368
- isPrimary={ isCurrent }
369
- aria-pressed={ isCurrent }
370
- aria-label={ option.label }
371
- key={ option.value }
372
- onClick={ () => setAttributes( { imageScale: option.value } ) }
373
- >
374
- { option.shortName }
375
- </Button>
376
- );
377
- } ) }
378
- </ButtonGroup>
379
- </PanelRow>
380
- </BaseControl>
381
- </Fragment>
382
- ) }
383
-
384
- { showImage && mediaPosition === 'behind' && (
385
- <RangeControl
386
- label={ __( 'Minimum height', 'newspack-blocks' ) }
387
- help={ __(
388
- "Sets a minimum height for the block, using a percentage of the screen's current height.",
389
- 'newspack-blocks'
390
- ) }
391
- value={ minHeight }
392
- onChange={ value => setAttributes( { minHeight: value } ) }
393
- min={ 0 }
394
- max={ 100 }
395
- required
396
- />
397
- ) }
398
- </PanelBody>
399
- <PanelBody title={ __( 'Post Control Settings', 'newspack-blocks' ) }>
400
- <PanelRow>
401
- <ToggleControl
402
- label={ __( 'Show Excerpt', 'newspack-blocks' ) }
403
- checked={ showExcerpt }
404
- onChange={ () => setAttributes( { showExcerpt: ! showExcerpt } ) }
405
- />
406
- </PanelRow>
407
- <RangeControl
408
- className="type-scale-slider"
409
- label={ __( 'Type Scale', 'newspack-blocks' ) }
410
- value={ typeScale }
411
- onChange={ value => setAttributes( { typeScale: value } ) }
412
- min={ 1 }
413
- max={ 10 }
414
- beforeIcon="editor-textcolor"
415
- afterIcon="editor-textcolor"
416
- required
417
- />
418
- </PanelBody>
419
- <PanelColorSettings
420
- title={ __( 'Color Settings', 'newspack-blocks' ) }
421
- initialOpen={ true }
422
- colorSettings={ [
423
- {
424
- value: textColor.color,
425
- onChange: setTextColor,
426
- label: __( 'Text Color', 'newspack-blocks' ),
427
- },
428
- ] }
429
- />
430
- <PanelBody title={ __( 'Post Meta Settings', 'newspack-blocks' ) }>
431
- <PanelRow>
432
- <ToggleControl
433
- label={ __( 'Show Date', 'newspack-blocks' ) }
434
- checked={ showDate }
435
- onChange={ () => setAttributes( { showDate: ! showDate } ) }
436
- />
437
- </PanelRow>
438
- <PanelRow>
439
- <ToggleControl
440
- label={ __( 'Show Category', 'newspack-blocks' ) }
441
- checked={ showCategory }
442
- onChange={ () => setAttributes( { showCategory: ! showCategory } ) }
443
- />
444
- </PanelRow>
445
- <PanelRow>
446
- <ToggleControl
447
- label={ __( 'Show Author', 'newspack-blocks' ) }
448
- checked={ showAuthor }
449
- onChange={ () => setAttributes( { showAuthor: ! showAuthor } ) }
450
- />
451
- </PanelRow>
452
- { showAuthor && (
453
- <PanelRow>
454
- <ToggleControl
455
- label={ __( 'Show Author Avatar', 'newspack-blocks' ) }
456
- checked={ showAvatar }
457
- onChange={ () => setAttributes( { showAvatar: ! showAvatar } ) }
458
- />
459
- </PanelRow>
460
- ) }
461
- </PanelBody>
462
- </Fragment>
463
- );
464
- };
465
-
466
- render() {
467
- /**
468
- * Constants
469
- */
470
- const {
471
- attributes,
472
- className,
473
- setAttributes,
474
- isSelected,
475
- latestPosts,
476
- hasPosts,
477
- textColor,
478
- } = this.props; // variables getting pulled out of props
479
- const {
480
- showExcerpt,
481
- showDate,
482
- showImage,
483
- imageShape,
484
- showAuthor,
485
- showAvatar,
486
- postsToShow,
487
- postLayout,
488
- mediaPosition,
489
- moreButton,
490
- moreButtonText,
491
- columns,
492
- categories,
493
- typeScale,
494
- imageScale,
495
- mobileStack,
496
- sectionHeader,
497
- showCaption,
498
- showCategory,
499
- specificMode,
500
- } = attributes;
501
-
502
- const classes = classNames( className, {
503
- 'is-grid': postLayout === 'grid',
504
- 'show-image': showImage,
505
- [ `columns-${ columns }` ]: postLayout === 'grid',
506
- [ `ts-${ typeScale }` ]: typeScale !== '5',
507
- [ `image-align${ mediaPosition }` ]: showImage,
508
- [ `is-${ imageScale }` ]: imageScale !== '1' && showImage,
509
- 'mobile-stack': mobileStack,
510
- [ `image-shape${ imageShape }` ]: imageShape !== 'landscape',
511
- 'has-text-color': textColor.color !== '',
512
- 'show-caption': showCaption,
513
- 'show-category': showCategory,
514
- wpnbha: true,
515
- } );
516
-
517
- const blockControls = [
518
- {
519
- icon: 'list-view',
520
- title: __( 'List View', 'newspack-blocks' ),
521
- onClick: () => setAttributes( { postLayout: 'list' } ),
522
- isActive: postLayout === 'list',
523
- },
524
- {
525
- icon: 'grid-view',
526
- title: __( 'Grid View', 'newspack-blocks' ),
527
- onClick: () => setAttributes( { postLayout: 'grid' } ),
528
- isActive: postLayout === 'grid',
529
- },
530
- ];
531
-
532
- const blockControlsImages = [
533
- {
534
- icon: 'align-none',
535
- title: __( 'Show media on top', 'newspack-blocks' ),
536
- isActive: mediaPosition === 'top',
537
- onClick: () => setAttributes( { mediaPosition: 'top' } ),
538
- },
539
- {
540
- icon: 'align-pull-left',
541
- title: __( 'Show media on left', 'newspack-blocks' ),
542
- isActive: mediaPosition === 'left',
543
- onClick: () => setAttributes( { mediaPosition: 'left' } ),
544
- },
545
- {
546
- icon: 'align-pull-right',
547
- title: __( 'Show media on right', 'newspack-blocks' ),
548
- isActive: mediaPosition === 'right',
549
- onClick: () => setAttributes( { mediaPosition: 'right' } ),
550
- },
551
- {
552
- icon: coverIcon,
553
- title: __( 'Show media behind', 'newspack-blocks' ),
554
- isActive: mediaPosition === 'behind',
555
- onClick: () => setAttributes( { mediaPosition: 'behind' } ),
556
- },
557
- ];
558
-
559
- const blockControlsImageShape = [
560
- {
561
- icon: landscapeIcon,
562
- title: __( 'Landscape Image Shape', 'newspack-blocks' ),
563
- isActive: imageShape === 'landscape',
564
- onClick: () => setAttributes( { imageShape: 'landscape' } ),
565
- },
566
- {
567
- icon: portraitIcon,
568
- title: __( 'portrait Image Shape', 'newspack-blocks' ),
569
- isActive: imageShape === 'portrait',
570
- onClick: () => setAttributes( { imageShape: 'portrait' } ),
571
- },
572
- {
573
- icon: squareIcon,
574
- title: __( 'Square Image Shape', 'newspack-blocks' ),
575
- isActive: imageShape === 'square',
576
- onClick: () => setAttributes( { imageShape: 'square' } ),
577
- },
578
- {
579
- icon: uncroppedIcon,
580
- title: __( 'Uncropped', 'newspack-blocks' ),
581
- isActive: imageShape === 'uncropped',
582
- onClick: () => setAttributes( { imageShape: 'uncropped' } ),
583
- },
584
- ];
585
-
586
- return (
587
- <Fragment>
588
- <div
589
- className={ classes }
590
- style={ {
591
- color: textColor.color,
592
- } }
593
- >
594
- <div>
595
- { latestPosts && ( ! RichText.isEmpty( sectionHeader ) || isSelected ) && (
596
- <RichText
597
- onChange={ value => setAttributes( { sectionHeader: value } ) }
598
- placeholder={ __( 'Write header…', 'newspack-blocks' ) }
599
- value={ sectionHeader }
600
- tagName="h2"
601
- className="article-section-title"
602
- />
603
- ) }
604
- { latestPosts && ! latestPosts.length && (
605
- <Placeholder>{ __( 'Sorry, no posts were found.', 'newspack-blocks' ) }</Placeholder>
606
- ) }
607
- { ! latestPosts && (
608
- <Placeholder>
609
- <Spinner />
610
- </Placeholder>
611
- ) }
612
- { latestPosts && latestPosts.map( post => this.renderPost( post ) ) }
613
- </div>
614
- </div>
615
-
616
- { ! specificMode && latestPosts && moreButton && (
617
- <div className="editor-styles-wrapper">
618
- <div className="wp-block-button">
619
- <RichText
620
- placeholder={ __( 'Load more posts', 'newspack-blocks' ) }
621
- value={ moreButtonText }
622
- onChange={ value => setAttributes( { moreButtonText: value } ) }
623
- className="wp-block-button__link"
624
- keepPlaceholderOnFocus
625
- allowedFormats={ [] }
626
- />
627
- </div>
628
- </div>
629
- ) }
630
-
631
- <BlockControls>
632
- <Toolbar controls={ blockControls } />
633
- { showImage && <Toolbar controls={ blockControlsImages } /> }
634
- { showImage && <Toolbar controls={ blockControlsImageShape } /> }
635
- </BlockControls>
636
- <InspectorControls>{ this.renderInspectorControls() }</InspectorControls>
637
- </Fragment>
638
- );
639
- }
640
- }
641
-
642
- export default compose( [
643
- withColors( { textColor: 'color' } ),
644
- withSelect( ( select, props ) => {
645
- const {
646
- postsToShow,
647
- authors,
648
- categories,
649
- tags,
650
- tagExclusions,
651
- specificPosts,
652
- specificMode,
653
- } = props.attributes;
654
- const { getAuthors, getEntityRecords } = select( 'core' );
655
- const latestPostsQuery = pickBy(
656
- specificMode && specificPosts && specificPosts.length
657
- ? {
658
- include: specificPosts,
659
- orderby: 'include',
660
- }
661
- : {
662
- per_page: postsToShow,
663
- categories,
664
- author: authors,
665
- tags,
666
- tags_exclude: tagExclusions,
667
- },
668
- value => ! isUndefined( value )
669
- );
670
- const postsListQuery = {
671
- per_page: 50,
672
- };
673
- return {
674
- latestPosts: getEntityRecords( 'postType', 'post', latestPostsQuery ),
675
- };
676
- } ),
677
- ] )( Edit );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/blog-posts-block/newspack-homepage-articles/blocks/homepage-articles/editor.js DELETED
@@ -1,7 +0,0 @@
1
- /**
2
- * Internal dependencies
3
- */
4
- import { registerBlockType } from '@wordpress/blocks';
5
- import { name, settings } from '.';
6
-
7
- registerBlockType( `newspack-blocks/${ name }`, settings );
 
 
 
 
 
 
 
trunk/blog-posts-block/newspack-homepage-articles/blocks/homepage-articles/editor.scss DELETED
@@ -1,39 +0,0 @@
1
- @import "../../shared/sass/variables";
2
-
3
- .type-scale-slider {
4
- .dashicon {
5
- height: 16px;
6
- width: 16px;
7
- }
8
-
9
- input + .dashicon {
10
- height: 24px;
11
- margin-left: 10px;
12
- margin-right: 0;
13
- width: 24px;
14
- }
15
- }
16
-
17
- .wpnbha {
18
- .editor-rich-text {
19
- width: 100%;
20
- }
21
-
22
- /* Article meta */
23
- .cat-links {
24
- font-size: $font__size-xs;
25
- }
26
-
27
- span.avatar {
28
- display: inline-block;
29
- margin-right: 0.5em;
30
- div {
31
- display: inline;
32
- }
33
- }
34
-
35
- /* Article excerpt */
36
- .excerpt-contain p {
37
- margin: 0.5em 0;
38
- }
39
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/blog-posts-block/newspack-homepage-articles/blocks/homepage-articles/index.js DELETED
@@ -1,106 +0,0 @@
1
- /**
2
- * External dependencies
3
- */
4
- import { Path, SVG } from '@wordpress/components';
5
- import { createBlock } from '@wordpress/blocks';
6
-
7
- /**
8
- * WordPress dependencies
9
- */
10
- import { applyFilters } from '@wordpress/hooks';
11
- import { __, _x } from '@wordpress/i18n';
12
-
13
- /**
14
- * Internal dependencies
15
- */
16
- import edit from './edit';
17
-
18
- /**
19
- * Style dependencies - will load in editor
20
- */
21
- import './editor.scss';
22
- import './view.scss';
23
- import metadata from './block.json';
24
- const { name, attributes, category } = metadata;
25
-
26
- // Name must be exported separately.
27
- export { name };
28
-
29
- export const title = __( 'Homepage Posts', 'newspack-blocks' );
30
-
31
- /* From https://material.io/tools/icons */
32
- export const icon = (
33
- <SVG xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
34
- <Path d="M0 0h24v24H0z" fill="none" />
35
- <Path d="M4 6H2v14c0 1.1.9 2 2 2h14v-2H4V6zm16-4H8c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm0 14H8V4h12v12zM10 9h8v2h-8zm0 3h4v2h-4zm0-6h8v2h-8z" />
36
- </SVG>
37
- );
38
-
39
- export const settings = {
40
- title,
41
- icon,
42
- attributes,
43
- category,
44
- keywords: [
45
- __( 'posts', 'newspack-blocks' ),
46
- __( 'articles', 'newspack-blocks' ),
47
- __( 'latest', 'newspack-blocks' ),
48
- ],
49
- description: __( 'A block for displaying homepage posts.', 'newspack-blocks' ),
50
- styles: [
51
- { name: 'default', label: _x( 'Default', 'block style', 'newspack-blocks' ), isDefault: true },
52
- { name: 'borders', label: _x( 'Borders', 'block style', 'newspack-blocks' ) },
53
- ],
54
- supports: {
55
- html: false,
56
- align: [ 'wide', 'full' ],
57
- default: '',
58
- },
59
- edit,
60
- save: () => null, // to use view.php
61
- transforms: {
62
- from: [
63
- {
64
- type: 'block',
65
- blocks: [ 'core/latest-posts' ],
66
- transform: ( {
67
- displayPostContent,
68
- displayPostDate,
69
- postLayout,
70
- columns,
71
- postsToShow,
72
- categories,
73
- } ) => {
74
- return createBlock(
75
- applyFilters( 'blocks.transforms_from_name', 'newspack-blocks/homepage-articles' ),
76
- {
77
- showExcerpt: displayPostContent,
78
- showDate: displayPostDate,
79
- postLayout,
80
- columns,
81
- postsToShow,
82
- showAuthor: false,
83
- categories: categories ? [ categories ] : [],
84
- }
85
- );
86
- },
87
- },
88
- ],
89
- to: [
90
- {
91
- type: 'block',
92
- blocks: [ 'core/latest-posts' ],
93
- transform: ( { showExcerpt, showDate, postLayout, columns, postsToShow, categories } ) => {
94
- return createBlock( 'core/latest-posts', {
95
- displayPostContent: showExcerpt,
96
- displayPostDate: showDate,
97
- postLayout,
98
- columns,
99
- postsToShow,
100
- categories: categories[ 0 ] || '',
101
- } );
102
- },
103
- },
104
- ],
105
- },
106
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/blog-posts-block/newspack-homepage-articles/blocks/homepage-articles/templates/article.php DELETED
@@ -1,143 +0,0 @@
1
- <?php
2
- /**
3
- * Article template.
4
- *
5
- * @global array $attributes Block attributes.
6
- * @package WordPress
7
- */
8
-
9
- call_user_func(
10
- function( $data ) {
11
- $attributes = $data['attributes'];
12
-
13
- $authors = Newspack_Blocks::prepare_authors();
14
-
15
- $styles = '';
16
-
17
- if ( 'behind' === $attributes['mediaPosition'] && $attributes['showImage'] && has_post_thumbnail() ) {
18
- $styles = 'min-height: ' . $attributes['minHeight'] . 'vh; padding-top: ' . ( $attributes['minHeight'] / 5 ) . 'vh;';
19
- }
20
- $image_size = 'newspack-article-block-uncropped';
21
- if ( has_post_thumbnail() && 'uncropped' !== $attributes['imageShape'] ) {
22
- $image_size = Newspack_Blocks::image_size_for_orientation( $attributes['imageShape'] );
23
- }
24
- $thumbnail_args = '';
25
- // If the image position is behind, pass the object-fit setting to maintain styles with AMP.
26
- if ( 'behind' === $attributes['mediaPosition'] ) {
27
- $thumbnail_args = array( 'object-fit' => 'cover' );
28
- }
29
- $category = false;
30
- // Use Yoast primary category if set.
31
- if ( class_exists( 'WPSEO_Primary_Term' ) ) {
32
- $primary_term = new WPSEO_Primary_Term( 'category', get_the_ID() );
33
- $category_id = $primary_term->get_primary_term();
34
- if ( $category_id ) {
35
- $category = get_term( $category_id );
36
- }
37
- }
38
- if ( ! $category ) {
39
- $categories_list = get_the_category();
40
- if ( ! empty( $categories_list ) ) {
41
- $category = $categories_list[0];
42
- }
43
- }
44
- ?>
45
- <article data-post-id="<?php the_id(); ?>"
46
- <?php if ( has_post_thumbnail() ) : ?>
47
- class="post-has-image"
48
- <?php endif; ?>
49
- <?php if ( $styles ) : ?>
50
- style="<?php echo esc_attr( $styles ); ?>"
51
- <?php endif; ?>
52
- >
53
- <?php if ( has_post_thumbnail() && $attributes['showImage'] && $attributes['imageShape'] ) : ?>
54
- <figure class="post-thumbnail">
55
- <a href="<?php the_permalink(); ?>" rel="bookmark">
56
- <?php the_post_thumbnail( $image_size, $thumbnail_args ); ?>
57
- </a>
58
-
59
- <?php if ( $attributes['showCaption'] && '' !== get_the_post_thumbnail_caption() ) : ?>
60
- <figcaption><?php the_post_thumbnail_caption(); ?></figcaption>
61
- <?php endif; ?>
62
- </figure><!-- .featured-image -->
63
- <?php endif; ?>
64
-
65
- <div class="entry-wrapper">
66
- <?php if ( $attributes['showCategory'] && $category ) : ?>
67
- <div class="cat-links">
68
- <a href="<?php echo esc_url( get_category_link( $category->term_id ) ); ?>">
69
- <?php echo esc_html( $category->name ); ?>
70
- </a>
71
- </div>
72
- <?php
73
- endif;
74
- if ( '' === $attributes['sectionHeader'] ) :
75
- the_title( '<h2 class="entry-title"><a href="' . esc_url( get_permalink() ) . '" rel="bookmark">', '</a></h2>' );
76
- else :
77
- the_title( '<h3 class="entry-title"><a href="' . esc_url( get_permalink() ) . '" rel="bookmark">', '</a></h3>' );
78
- endif;
79
- if ( $attributes['showExcerpt'] ) :
80
- the_excerpt();
81
- endif;
82
- if ( $attributes['showAuthor'] || $attributes['showDate'] ) :
83
- ?>
84
- <div class="entry-meta">
85
- <?php
86
- if ( $attributes['showAuthor'] ) :
87
- if ( $attributes['showAvatar'] ) :
88
- echo wp_kses(
89
- newspack_blocks_format_avatars( $authors ),
90
- array(
91
- 'img' => array(
92
- 'class' => true,
93
- 'src' => true,
94
- 'alt' => true,
95
- 'width' => true,
96
- 'height' => true,
97
- 'data-*' => true,
98
- 'srcset' => true,
99
- ),
100
- 'noscript' => array(),
101
- 'a' => array(
102
- 'href' => true,
103
- ),
104
- )
105
- );
106
- endif;
107
- ?>
108
- <span class="byline">
109
- <?php echo wp_kses_post( newspack_blocks_format_byline( $authors ) ); ?>
110
- </span><!-- .author-name -->
111
- <?php
112
- endif;
113
- if ( $attributes['showDate'] ) :
114
- $time_string = '<time class="entry-date published updated" datetime="%1$s">%2$s</time>';
115
- if ( get_the_time( 'U' ) !== get_the_modified_time( 'U' ) ) :
116
- $time_string = '<time class="entry-date published" datetime="%1$s">%2$s</time><time class="updated" datetime="%3$s">%4$s</time>';
117
- endif;
118
- printf(
119
- wp_kses(
120
- $time_string,
121
- array(
122
- 'time' => array(
123
- 'class' => true,
124
- 'datetime' => true,
125
- ),
126
- )
127
- ),
128
- esc_attr( get_the_date( DATE_W3C ) ),
129
- esc_html( get_the_date() ),
130
- esc_attr( get_the_modified_date( DATE_W3C ) ),
131
- esc_html( get_the_modified_date() )
132
- );
133
- endif;
134
- ?>
135
- </div><!-- .entry-meta -->
136
- <?php endif; ?>
137
- </div><!-- .entry-wrapper -->
138
- </article>
139
-
140
- <?php
141
- },
142
- $data // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable
143
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/blog-posts-block/newspack-homepage-articles/blocks/homepage-articles/templates/articles-list.php DELETED
@@ -1,21 +0,0 @@
1
- <?php
2
- /**
3
- * Article list template.
4
- *
5
- * @global WP_Query $article_query Article query.
6
- * @global array $attributes
7
- * @package WordPress
8
- */
9
-
10
- call_user_func(
11
- function( $data ) {
12
- echo Newspack_Blocks::template_inc( // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
13
- __DIR__ . '/articles-loop.php',
14
- array(
15
- 'attributes' => $data['attributes'],
16
- 'article_query' => $data['article_query'],
17
- )
18
- );
19
- },
20
- $data // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable
21
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/blog-posts-block/newspack-homepage-articles/blocks/homepage-articles/templates/articles-loop.php DELETED
@@ -1,29 +0,0 @@
1
- <?php
2
- /**
3
- * Articles loop template.
4
- *
5
- * @package WordPress
6
- * @global \WP_Query $article_query Article query.
7
- * @global array $attributes
8
- * @global array $newspack_blocks_post_id
9
- */
10
-
11
- call_user_func(
12
- function( $data ) {
13
- $attributes = $data['attributes'];
14
- $article_query = $data['article_query'];
15
- global $newspack_blocks_post_id;
16
- $post_counter = 0;
17
- while ( $article_query->have_posts() ) {
18
- $article_query->the_post();
19
- if ( ! $attributes['specificMode'] && ( isset( $newspack_blocks_post_id[ get_the_ID() ] ) || $post_counter >= $attributes['postsToShow'] ) ) {
20
- continue;
21
- }
22
- $newspack_blocks_post_id[ get_the_ID() ] = true;
23
- $post_counter++;
24
- echo Newspack_Blocks::template_inc( __DIR__ . '/article.php', array( 'attributes' => $attributes ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
25
- }
26
- wp_reset_postdata();
27
- },
28
- $data // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable
29
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/blog-posts-block/newspack-homepage-articles/blocks/homepage-articles/view.js DELETED
@@ -1,236 +0,0 @@
1
- /**
2
- * VIEW
3
- * JavaScript used on front of site.
4
- */
5
-
6
- /**
7
- * Style dependencies
8
- */
9
- import './view.scss';
10
-
11
- const btnURLAttr = 'data-load-more-url';
12
- const fetchRetryCount = 3;
13
-
14
- /**
15
- * Load More Button Handling
16
- */
17
-
18
- document.querySelectorAll( '[data-load-more-btn]' ).forEach( attachLoadMoreHandler );
19
-
20
- /**
21
- * Attaches an event handler to the Load more button.
22
- * @param {DOMElement} btnEl the button that was clicked
23
- */
24
- function attachLoadMoreHandler( btnEl ) {
25
- if ( ! btnEl ) {
26
- return null;
27
- }
28
-
29
- const handler = buildLoadMoreHandler( btnEl );
30
-
31
- btnEl.addEventListener( 'click', handler );
32
- }
33
-
34
- /**
35
- * Builds a function to handle clicks on the load more button.
36
- * Creates internal state via closure to ensure all state is
37
- * isolated to a single Block + button instance.
38
- *
39
- * @param {DOMElement} btnEl the button that was clicked
40
- */
41
- function buildLoadMoreHandler( btnEl ) {
42
- // Set elements from scope determined by the clicked "Load more" button.
43
- const blockWrapperEl = btnEl.parentElement; // scope root element
44
- const postsContainerEl = blockWrapperEl.querySelector( '[data-posts-container]' );
45
- const loadingEl = blockWrapperEl.querySelector( '[data-load-more-loading-text]' );
46
- const errorEl = blockWrapperEl.querySelector( '[data-load-more-error-text]' );
47
-
48
- // Set initial state flags.
49
- let isFetching = false;
50
- let isEndOfData = false;
51
-
52
- return () => {
53
- // Early return if still fetching or no more posts to render.
54
- if ( isFetching || isEndOfData ) {
55
- return false;
56
- }
57
-
58
- isFetching = true;
59
-
60
- // Set elements visibility for fetching state.
61
- hideEl( btnEl );
62
- hideEl( errorEl );
63
- showEl( loadingEl );
64
-
65
- const requestURL = new URL( btnEl.getAttribute( btnURLAttr ) );
66
-
67
- // Set currenty rendered posts' IDs as a query param (e.g. exclude_ids=1,2,3)
68
- requestURL.searchParams.set( 'exclude_ids', getRenderedPostsIds().join( ',' ) );
69
-
70
- fetchWithRetry( { url: requestURL.toString(), onSuccess, onError }, fetchRetryCount );
71
-
72
- function onSuccess( data ) {
73
- // Validate received data.
74
- if ( ! isPostsDataValid( data ) ) {
75
- return onError();
76
- }
77
-
78
- if ( data.items.length ) {
79
- // Render posts' HTML from string.
80
- const postsHTML = data.items.map( item => item.html ).join( '' );
81
- postsContainerEl.insertAdjacentHTML( 'beforeend', postsHTML );
82
- }
83
-
84
- if ( data.next ) {
85
- // Save next URL as button's attribute.
86
- btnEl.setAttribute( btnURLAttr, data.next );
87
-
88
- // Unhide button since there are more posts available.
89
- showEl( btnEl );
90
- }
91
-
92
- if ( ! data.items.length || ! data.next ) {
93
- isEndOfData = true;
94
- }
95
-
96
- isFetching = false;
97
-
98
- hideEl( loadingEl );
99
- }
100
-
101
- function onError() {
102
- isFetching = false;
103
-
104
- // Display error message and keep the button visible to enable retrying.
105
- hideEl( loadingEl );
106
- showEl( errorEl );
107
- showEl( btnEl );
108
- }
109
- };
110
- }
111
-
112
- /**
113
- * Returns unique IDs for posts that are currently in the DOM.
114
- */
115
- function getRenderedPostsIds() {
116
- const postEls = document.querySelectorAll( 'article[data-post-id]' );
117
- const postIds = Array.from( postEls ).map( el => el.getAttribute( 'data-post-id' ) );
118
-
119
- return [ ...new Set( postIds ) ]; // Make values unique with Set
120
- }
121
-
122
- /**
123
- * Wrapper for XMLHttpRequest that performs given number of retries when error
124
- * occurs.
125
- *
126
- * @param {Object} options XMLHttpRequest options
127
- * @param {Number} n retry count before throwing
128
- */
129
- function fetchWithRetry( options, n ) {
130
- const xhr = new XMLHttpRequest();
131
-
132
- xhr.onreadystatechange = () => {
133
- // Return if the request is completed.
134
- if ( xhr.readyState !== 4 ) {
135
- return;
136
- }
137
-
138
- // Call onSuccess with parsed JSON if the request is successful.
139
- if ( xhr.status >= 200 && xhr.status < 300 ) {
140
- const data = JSON.parse( xhr.responseText );
141
-
142
- return options.onSuccess( data );
143
- }
144
-
145
- // Call onError if the request has failed n + 1 times (or if n is undefined).
146
- if ( ! n ) {
147
- return options.onError();
148
- }
149
-
150
- // Retry fetching if request has failed and n > 0.
151
- return fetchWithRetry( options, n - 1 );
152
- };
153
-
154
- xhr.open( 'GET', options.url );
155
- xhr.send();
156
- }
157
-
158
- /**
159
- * Validates the "Load more" posts endpoint schema:
160
- * {
161
- * "type": "object",
162
- * "properties": {
163
- * "items": {
164
- * "type": "array",
165
- * "items": {
166
- * "type": "object",
167
- * "properties": {
168
- * "html": {
169
- * "type": "string"
170
- * }
171
- * },
172
- * "required": ["html"]
173
- * },
174
- * "required": ["items"]
175
- * },
176
- * "next": {
177
- * "type": ["string", "null"]
178
- * }
179
- * },
180
- * "required": ["items", "next"]
181
- * }
182
- *
183
- * @param {Object} data posts endpoint payload
184
- */
185
- function isPostsDataValid( data ) {
186
- let isValid = false;
187
-
188
- if (
189
- data &&
190
- hasOwnProp( data, 'items' ) &&
191
- Array.isArray( data.items ) &&
192
- hasOwnProp( data, 'next' ) &&
193
- typeof data.next === 'string'
194
- ) {
195
- isValid = true;
196
-
197
- if (
198
- data.items.length &&
199
- ! ( hasOwnProp( data.items[ 0 ], 'html' ) && typeof data.items[ 0 ].html === 'string' )
200
- ) {
201
- isValid = false;
202
- }
203
- }
204
-
205
- return isValid;
206
- }
207
-
208
- /**
209
- * Hides given DOM element.
210
- *
211
- * @param {DOMElement} el
212
- */
213
- function hideEl( el ) {
214
- el.style.display = 'none';
215
- el.setAttribute( 'hidden', '' );
216
- }
217
-
218
- /**
219
- * Unhides given DOM element.
220
- *
221
- * @param {DOMElement} el
222
- */
223
- function showEl( el ) {
224
- el.style.display = '';
225
- el.removeAttribute( 'hidden' );
226
- }
227
-
228
- /**
229
- * Checks if object has own property.
230
- *
231
- * @param {Object} obj
232
- * @param {String} prop
233
- */
234
- function hasOwnProp( obj, prop ) {
235
- return Object.prototype.hasOwnProperty.call( obj, prop );
236
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/blog-posts-block/newspack-homepage-articles/blocks/homepage-articles/view.php DELETED
@@ -1,227 +0,0 @@
1
- <?php
2
- /**
3
- * Server-side rendering of the `newspack-blocks/homepage-posts` block.
4
- *
5
- * @package WordPress
6
- */
7
-
8
- /**
9
- * Renders the `newspack-blocks/homepage-posts` block on server.
10
- *
11
- * @param array $attributes The block attributes.
12
- *
13
- * @return string Returns the post content with latest posts added.
14
- */
15
- function newspack_blocks_render_block_homepage_articles( $attributes ) {
16
- $article_query = new WP_Query( Newspack_Blocks::build_articles_query( $attributes ) );
17
-
18
- $classes = Newspack_Blocks::block_classes( 'homepage-articles', $attributes, array( 'wpnbha' ) );
19
-
20
- if ( isset( $attributes['postLayout'] ) && 'grid' === $attributes['postLayout'] ) {
21
- $classes .= ' is-grid';
22
- }
23
- if ( isset( $attributes['columns'] ) && 'grid' === $attributes['postLayout'] ) {
24
- $classes .= ' columns-' . $attributes['columns'];
25
- }
26
- if ( $attributes['showImage'] ) {
27
- $classes .= ' show-image';
28
- }
29
- if ( $attributes['showImage'] && isset( $attributes['mediaPosition'] ) ) {
30
- $classes .= ' image-align' . $attributes['mediaPosition'];
31
- }
32
- if ( isset( $attributes['typeScale'] ) ) {
33
- $classes .= ' ts-' . $attributes['typeScale'];
34
- }
35
- if ( $attributes['showImage'] && isset( $attributes['imageScale'] ) ) {
36
- $classes .= ' is-' . $attributes['imageScale'];
37
- }
38
- if ( $attributes['showImage'] && $attributes['mobileStack'] ) {
39
- $classes .= ' mobile-stack';
40
- }
41
- if ( $attributes['showCaption'] ) {
42
- $classes .= ' show-caption';
43
- }
44
- if ( $attributes['showCategory'] ) {
45
- $classes .= ' show-category';
46
- }
47
- if ( isset( $attributes['className'] ) ) {
48
- $classes .= ' ' . $attributes['className'];
49
- }
50
-
51
- if ( '' !== $attributes['textColor'] || '' !== $attributes['customTextColor'] ) {
52
- $classes .= ' has-text-color';
53
- }
54
- if ( '' !== $attributes['textColor'] ) {
55
- $classes .= ' has-' . $attributes['textColor'] . '-color';
56
- }
57
-
58
- $styles = '';
59
-
60
- if ( '' !== $attributes['customTextColor'] ) {
61
- $styles = 'color: ' . $attributes['customTextColor'] . ';';
62
- }
63
-
64
- $articles_rest_url = add_query_arg(
65
- array_merge(
66
- array_map(
67
- function( $attribute ) {
68
- return false === $attribute ? '0' : $attribute;
69
- },
70
- $attributes
71
- ),
72
- array( 'page' => 2 )
73
- ),
74
- rest_url( '/newspack-blocks/v1/articles' )
75
- );
76
-
77
- ob_start();
78
-
79
- if ( $article_query->have_posts() ) : ?>
80
- <div class="<?php echo esc_attr( $classes ); ?>" style="<?php echo esc_attr( $styles ); ?>">
81
- <div data-posts-container>
82
- <?php if ( '' !== $attributes['sectionHeader'] ) : ?>
83
- <h2 class="article-section-title">
84
- <span><?php echo wp_kses_post( $attributes['sectionHeader'] ); ?></span>
85
- </h2>
86
- <?php endif; ?>
87
- <?php
88
-
89
- /*
90
- * We are not using an AMP-based renderer on AMP requests because it has limitations
91
- * around dynamically calculating the height of the the article list on load.
92
- * As a result we render the same standards-based markup for all requests.
93
- */
94
-
95
- echo Newspack_Blocks::template_inc(
96
- __DIR__ . '/templates/articles-list.php',
97
- array(
98
- 'articles_rest_url' => $articles_rest_url,
99
- 'article_query' => $article_query,
100
- 'attributes' => $attributes,
101
- )
102
- );
103
- ?>
104
- </div>
105
- <?php
106
-
107
- /*
108
- * AMP-requests cannot contain client-side scripting (eg: JavaScript). As a result
109
- * we do not display the "More" button on AMP-requests. This feature is deliberately
110
- * disabled.
111
- *
112
- * @see https://github.com/Automattic/newspack-blocks/pull/226#issuecomment-558695909
113
- * @see https://wp.me/paYJgx-jW
114
- */
115
- $page = $article_query->paged ?? 1;
116
-
117
- $has_more_pages = ( ++$page ) <= $article_query->max_num_pages;
118
-
119
- if ( ! Newspack_Blocks::is_amp() && $has_more_pages && boolval( $attributes['moreButton'] ) ) :
120
- ?>
121
- <button type="button" data-load-more-btn data-load-more-url="<?php echo esc_url( $articles_rest_url ); ?>">
122
- <?php
123
- if ( ! empty( $attributes['moreButtonText'] ) ) {
124
- echo esc_html( $attributes['moreButtonText'] );
125
- } else {
126
- esc_html_e( 'Load more posts', 'newspack-blocks' );
127
- }
128
- ?>
129
- </button>
130
- <p data-load-more-loading-text hidden>
131
- <?php _e( 'Loading...', 'newspack-blocks' ); ?>
132
- </p>
133
- <p data-load-more-error-text hidden>
134
- <?php _e( 'Something went wrong. Please refresh the page and/or try again.', 'newspack-blocks' ); ?>
135
- </p>
136
- <?php endif; ?>
137
-
138
- </div>
139
- <?php
140
- endif;
141
-
142
- $content = ob_get_clean();
143
- Newspack_Blocks::enqueue_view_assets( 'homepage-articles' );
144
-
145
- return $content;
146
- }
147
-
148
- /**
149
- * Registers the `newspack-blocks/homepage-articles` block on server.
150
- */
151
- function newspack_blocks_register_homepage_articles() {
152
- $block = json_decode(
153
- file_get_contents( __DIR__ . '/block.json' ), // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
154
- true
155
- );
156
- register_block_type(
157
- apply_filters( 'newspack_blocks_block_name', 'newspack-blocks/' . $block['name'] ),
158
- apply_filters(
159
- 'newspack_blocks_block_args',
160
- array(
161
- 'attributes' => $block['attributes'],
162
- 'render_callback' => 'newspack_blocks_render_block_homepage_articles',
163
- ),
164
- $block['name']
165
- )
166
- );
167
- }
168
- add_action( 'init', 'newspack_blocks_register_homepage_articles' );
169
-
170
-
171
- /**
172
- * Renders author avatar markup.
173
- *
174
- * @param array $author_info Author info array.
175
- *
176
- * @return string Returns formatted Avatar markup
177
- */
178
- function newspack_blocks_format_avatars( $author_info ) {
179
- $elements = array_map(
180
- function ( $author ) {
181
- return sprintf( '<a href="%s">%s</a>', $author->url, $author->avatar );
182
- },
183
- $author_info
184
- );
185
-
186
- return implode( '', $elements );
187
- }
188
-
189
- /**
190
- * Renders byline markup.
191
- *
192
- * @param array $author_info Author info array.
193
- *
194
- * @return string Returns byline markup.
195
- */
196
- function newspack_blocks_format_byline( $author_info ) {
197
- $index = -1;
198
- $elements = array_merge(
199
- array(
200
- esc_html_x( 'by', 'post author', 'newspack-blocks' ) . ' ',
201
- ),
202
- array_reduce(
203
- $author_info,
204
- function ( $accumulator, $author ) use ( $author_info, &$index ) {
205
- $index ++;
206
- $penultimate = count( $author_info ) - 2;
207
-
208
- return array_merge(
209
- $accumulator,
210
- array(
211
- sprintf(
212
- /* translators: 1: author link. 2: author name. 3. variable seperator (comma, 'and', or empty) */
213
- '<span class="author vcard"><a class="url fn n" href="%1$s">%2$s</a></span>',
214
- esc_url( get_author_posts_url( $author->ID ) ),
215
- esc_html( $author->display_name )
216
- ),
217
- ( $index < $penultimate ) ? ', ' : '',
218
- ( count( $author_info ) > 1 && $penultimate === $index ) ? esc_html_x( ' and ', 'post author', 'newspack-blocks' ) : '',
219
- )
220
- );
221
- },
222
- array()
223
- )
224
- );
225
-
226
- return implode( '', $elements );
227
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/blog-posts-block/newspack-homepage-articles/blocks/homepage-articles/view.scss DELETED
@@ -1,582 +0,0 @@
1
- @import "../../shared/sass/variables";
2
- @import "../../shared/sass/mixins";
3
-
4
- .wpnbha {
5
- margin-bottom: 1em;
6
-
7
- article {
8
- margin-bottom: 1.5em;
9
- word-break: break-word;
10
- overflow-wrap: break-word;
11
- position: relative;
12
-
13
- &:last-of-type {
14
- margin-bottom: 0;
15
- }
16
- }
17
-
18
- /* Section header */
19
- .article-section-title {
20
- font-size: $font__size-sm;
21
- margin-bottom: 0.5em;
22
- width: 100%; // make sure this isn't caught up in the flex styles.
23
- }
24
-
25
- /* Column styles */
26
- &.is-grid > div {
27
- display: flex;
28
- flex-wrap: wrap;
29
- justify-content: space-between;
30
- padding: 0;
31
- list-style: none;
32
- }
33
-
34
- &.is-grid {
35
- article {
36
- flex-basis: 100%;
37
-
38
- @include media(tablet) {
39
- &:last-child,
40
- & {
41
- margin-bottom: 1em;
42
- }
43
- }
44
- }
45
- }
46
-
47
- @include media(mobile) {
48
- &.columns-3 article,
49
- &.columns-6 article {
50
- flex-basis: calc( 33.333% - 16px );
51
- }
52
-
53
- &.columns-2 article,
54
- &.columns-4 article,
55
- &.columns-5 article {
56
- flex-basis: calc( 50% - 16px);
57
- }
58
-
59
- &.columns-5 article:last-of-type:nth-child(odd) {
60
- flex-grow: 1;
61
- }
62
- }
63
-
64
- @include media(tablet) {
65
- @for $i from 2 through 6 {
66
- &.columns-#{ $i } article {
67
- flex-basis: calc( ( 100% / #{$i} ) - 16px );
68
- }
69
- }
70
- }
71
-
72
- /* Image styles */
73
-
74
- .post-thumbnail {
75
- margin: 0;
76
-
77
- img {
78
- height: auto;
79
- width: 100%;
80
- }
81
- }
82
-
83
- figcaption {
84
- font-size: $font__size-xxs;
85
- }
86
-
87
- .post-thumbnail {
88
- margin-bottom: 0.25em;
89
-
90
- figcaption {
91
- margin-bottom: 0.5em;
92
- }
93
- }
94
-
95
- &.image-alignleft,
96
- &.image-alignright {
97
- .post-has-image {
98
- display: flex;
99
-
100
- .post-thumbnail {
101
- flex-basis: 33%;
102
- }
103
- .entry-wrapper {
104
- flex-basis: 67%;
105
- }
106
- }
107
-
108
- &.mobile-stack .post-has-image {
109
- display: block;
110
- }
111
-
112
- @include media(mobile) {
113
- &.mobile-stack .post-has-image {
114
- display: flex;
115
- }
116
- }
117
-
118
- // Image scale
119
- @include media(mobile) {
120
- &.is-4 {
121
- .post-thumbnail {
122
- flex-basis: 75%;
123
- }
124
- .entry-wrapper {
125
- flex-basis: 25%;
126
- }
127
- }
128
-
129
- &.is-3 {
130
- .post-thumbnail,
131
- .entry-wrapper {
132
- flex-basis: 50%;
133
- }
134
- }
135
-
136
- // is-2 matches the mobile default above
137
- }
138
-
139
- &.is-1 {
140
- .post-thumbnail {
141
- flex-basis: 25%;
142
- }
143
- .entry-wrapper {
144
- flex-basis: 75%;
145
- }
146
- }
147
- }
148
-
149
- &.image-alignleft .post-thumbnail {
150
- margin-right: 1em;
151
- }
152
-
153
- &.image-alignright {
154
- .post-thumbnail {
155
- margin-left: 1em;
156
- }
157
-
158
- .entry-wrapper {
159
- order: -1;
160
- }
161
- }
162
-
163
- &.mobile-stack {
164
- &.image-alignleft,
165
- &.image-alignright {
166
- .post-thumbnail {
167
- margin-left: 0;
168
- margin-right: 0;
169
- }
170
- }
171
- }
172
-
173
- @include media( mobile ) {
174
- &.mobile-stack.image-alignleft .post-thumbnail {
175
- margin-right: 1em;
176
- }
177
-
178
- &.mobile-stack.image-alignright .post-thumbnail {
179
- margin-left: 1em;
180
- }
181
- }
182
-
183
- /* Headings */
184
- .entry-title {
185
- margin: 0 0 0.25em;
186
- a {
187
- color: inherit;
188
- text-decoration: none;
189
- }
190
- }
191
-
192
- /* Article meta */
193
- .cat-links {
194
- font-size: $font__size-xxs;
195
- font-weight: bold;
196
- margin: 0 0 0.5em;
197
-
198
- a {
199
- text-decoration: none;
200
-
201
- &:hover {
202
- text-decoration: underline;
203
- }
204
- }
205
- }
206
-
207
- .entry-meta {
208
- display: flex;
209
- flex-wrap: wrap;
210
- align-items: center;
211
- margin-top: 0.5em;
212
-
213
- .byline:not(:last-child) {
214
- margin-right: 1.5em;
215
- }
216
-
217
- .updated:not(.published) {
218
- display: none;
219
- }
220
- }
221
-
222
- .avatar {
223
- border-radius: 100%;
224
- display: block;
225
- margin-right: 0.5em;
226
- }
227
-
228
- p {
229
- margin: 0.5em 0;
230
- }
231
-
232
- &.has-text-color {
233
- .article-section-title,
234
- .entry-title,
235
- .entry-title a,
236
- .entry-title a:visited,
237
- .entry-meta,
238
- .entry-meta a,
239
- .entry-meta .byline a,
240
- .entry-meta .byline a:visited,
241
- .cat-links,
242
- .cat-links a,
243
- .cat-links a:visited,
244
- figcaption {
245
- color: inherit;
246
- }
247
- }
248
-
249
- &.has-text-color {
250
- .entry-meta span:not(.avatar) {
251
- opacity: 0.8;
252
- }
253
- }
254
-
255
- &.image-alignbehind {
256
- .post-has-image {
257
- display: flex;
258
- align-items: flex-end;
259
- position: relative;
260
-
261
- .post-thumbnail {
262
- bottom: 0;
263
- left: 0;
264
- margin: 0;
265
- overflow: hidden;
266
- position: absolute;
267
- right: 0;
268
- top: 0;
269
-
270
- img {
271
- height: 100%;
272
- object-fit: cover;
273
- max-width: 1000%;
274
- width: 100%;
275
- }
276
-
277
- figcaption {
278
- bottom: 1em;
279
- /* autoprefixer: ignore next */
280
- -webkit-box-orient: vertical;
281
- color: rgba(white, 0.9);
282
- display: -webkit-box;
283
- font-style: italic;
284
- left: 0;
285
- -webkit-line-clamp: 1;
286
- margin: 0;
287
- max-height: 1.6em;
288
- overflow: hidden;
289
- padding: 0 1em;
290
- position: absolute;
291
- right: 0;
292
- text-align: right;
293
- text-overflow: ellipsis;
294
- z-index: 2;
295
- }
296
-
297
- &:after {
298
- background: rgba( 0, 0, 0, 0.5 );
299
- bottom: 0;
300
- content: '';
301
- left: 0;
302
- position: absolute;
303
- right: 0;
304
- top: 0;
305
- z-index: 1;
306
- }
307
- }
308
-
309
- .entry-wrapper {
310
- padding: 2em;
311
- position: relative;
312
- z-index: 2;
313
- }
314
-
315
- .entry-wrapper,
316
- .entry-title a,
317
- .entry-meta,
318
- .entry-meta .byline a,
319
- .cat-links a {
320
- color: #fff;
321
- }
322
-
323
- }
324
- }
325
- }
326
-
327
- /* Some really rough font sizing */
328
- .wpnbha {
329
- /* 'Normal' size */
330
- article {
331
- .entry-title {
332
- font-size: 1.2em;
333
- }
334
- .entry-meta {
335
- font-size: 0.8em;
336
- }
337
-
338
- .avatar {
339
- height: 25px;
340
- width: 25px;
341
- }
342
-
343
- @include media(tablet) {
344
- .entry-title {
345
- font-size: 1.6em;
346
- }
347
-
348
- .avatar {
349
- height: 40px;
350
- width: 40px;
351
- }
352
- }
353
- }
354
-
355
- &.ts-10,
356
- &.ts-9,
357
- &.ts-8 {
358
- .entry-title {
359
- line-height: 1.1em;
360
- }
361
- @include media(tablet) {
362
- article .avatar {
363
- height: 2.4em;
364
- width: 2.4em;
365
- }
366
- }
367
-
368
- }
369
-
370
- &.ts-10 article {
371
- .entry-title {
372
- font-size: 2.6em;
373
- }
374
- @include media(tablet) {
375
- .entry-title {
376
- font-size: 3.6em;
377
- }
378
- }
379
- @include media(desktop) {
380
- .entry-title {
381
- font-size: 4.8em;
382
- }
383
- }
384
- }
385
-
386
- &.ts-9 article {
387
- .entry-title {
388
- font-size: 2.4em;
389
- }
390
- @include media(tablet) {
391
- .entry-title {
392
- font-size: 3.4em;
393
- }
394
- }
395
- @include media(desktop) {
396
- .entry-title {
397
- font-size: 4.2em;
398
- }
399
- }
400
- }
401
-
402
- &.ts-8 article {
403
- .entry-title {
404
- font-size: 2.2em;
405
- }
406
- @include media(tablet) {
407
- .entry-title {
408
- font-size: 3.0em;
409
- }
410
- }
411
- @include media(desktop) {
412
- .entry-title {
413
- font-size: 3.6em;
414
- }
415
- }
416
- }
417
-
418
- &.ts-7 article {
419
- .entry-title {
420
- font-size: 2em;
421
- }
422
- @include media( tablet) {
423
- .entry-title {
424
- font-size: 2.4em;
425
- }
426
- .avatar {
427
- height: 48px;
428
- width: 48px;
429
- }
430
- }
431
- @include media(desktop) {
432
- .entry-title {
433
- font-size: 3em;
434
- }
435
- }
436
- }
437
-
438
- &.ts-6 article {
439
- .entry-title {
440
- font-size: 1.7em;
441
- }
442
- @include media(tablet) {
443
- .entry-title {
444
- font-size: 2.0em;
445
- }
446
- .avatar {
447
- height: 44px;
448
- width: 44px;
449
- }
450
- }
451
- @include media(desktop) {
452
- .entry-title {
453
- font-size: 2.4em;
454
- }
455
- }
456
- }
457
-
458
- &.ts-5 article {
459
- .entry-title {
460
- font-size: 1.4em;
461
- }
462
- @include media(tablet) {
463
- .entry-title {
464
- font-size: 1.8em;
465
- }
466
- .avatar {
467
- height: 40px;
468
- width: 40px;
469
- }
470
- }
471
- @include media(desktop) {
472
- .entry-title {
473
- font-size: 2.0em;
474
- }
475
- }
476
- }
477
-
478
- /* Type Scale 4: default */
479
-
480
- &.ts-3 article {
481
- .entry-title {
482
- font-size: 1.0em;
483
- }
484
- .entry-wrapper p {
485
- font-size: 0.8em;
486
- }
487
- .entry-meta {
488
- font-size: 0.7em;
489
- }
490
- @include media( tablet ) {
491
- .entry-title {
492
- font-size: 1.2em
493
- }
494
-
495
- .avatar {
496
- height: 32px;
497
- width: 32px;
498
- }
499
- }
500
- }
501
-
502
- &.ts-2 article {
503
- .entry-title {
504
- font-size: 0.8em;
505
- }
506
- .entry-wrapper p,
507
- .entry-meta {
508
- font-size: 0.7em;
509
- }
510
-
511
- @include media( tablet ) {
512
- .entry-title {
513
- font-size: 0.9em;
514
- }
515
-
516
- .avatar {
517
- height: 28px;
518
- width: 28px;
519
- }
520
- }
521
- }
522
-
523
- &.ts-1 article {
524
- .entry-title,
525
- .entry-wrapper p {
526
- font-size: 0.7em;
527
- }
528
- .entry-meta {
529
- font-size: 0.6em;
530
- }
531
- @include media( tablet ) {
532
- .avatar {
533
- height: 24px;
534
- width: 24px;
535
- }
536
- }
537
- }
538
- }
539
-
540
- /* Block styles */
541
-
542
- .wpnbha.is-style-borders {
543
- article {
544
- border: solid rgba(0, 0, 0, 0.2);
545
- border-width: 0 0 1px;
546
- margin-bottom: 1em;
547
- padding-bottom: 1em;
548
-
549
- &:last-of-type {
550
- margin-bottom: 0;
551
-
552
- &:not(:first-of-type) {
553
- border-bottom: 0;
554
- }
555
- }
556
- }
557
-
558
- @include media(tablet) {
559
-
560
- @for $i from 2 through 6 {
561
- &.columns-#{ $i } article {
562
- padding-right: calc( ( 16px * #{$i} ) / ( #{$i} - 1 ) );
563
- }
564
- }
565
-
566
- &.is-grid {
567
- article {
568
- border-width: 0 1px 0 0;
569
- }
570
- }
571
-
572
- &.is-grid article:last-of-type,
573
- &.columns-1 article,
574
- &.columns-2 article:nth-of-type(2n),
575
- &.columns-3 article:nth-of-type(3n),
576
- &.columns-4 article:nth-of-type(4n),
577
- &.columns-5 article:nth-of-type(5n),
578
- &.columns-6 article:nth-of-type(6n) {
579
- border: 0;
580
- }
581
- }
582
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/blog-posts-block/newspack-homepage-articles/class-newspack-blocks-api.php DELETED
@@ -1,224 +0,0 @@
1
- <?php
2
- /**
3
- * Register Newspack Blocks rest fields
4
- *
5
- * @package Newspack_Blocks
6
- */
7
-
8
- /**
9
- * `Newspack_Blocks_API` is a wrapper for `register_rest_fields()`
10
- */
11
- class Newspack_Blocks_API {
12
-
13
- /**
14
- * Register Newspack REST fields.
15
- */
16
- public static function register_rest_fields() {
17
- register_rest_field(
18
- array( 'post', 'page' ),
19
- 'newspack_featured_image_src',
20
- array(
21
- 'get_callback' => array( 'Newspack_Blocks_API', 'newspack_blocks_get_image_src' ),
22
- 'schema' => array(
23
- 'context' => array(
24
- 'edit',
25
- ),
26
- 'type' => 'array',
27
- ),
28
- )
29
- );
30
-
31
- register_rest_field(
32
- array( 'post', 'page' ),
33
- 'newspack_featured_image_caption',
34
- array(
35
- 'get_callback' => array( 'Newspack_Blocks_API', 'newspack_blocks_get_image_caption' ),
36
- 'schema' => array(
37
- 'context' => array(
38
- 'edit',
39
- ),
40
- 'type' => 'string',
41
- ),
42
- )
43
- );
44
-
45
- /* Add author info source */
46
- register_rest_field(
47
- 'post',
48
- 'newspack_author_info',
49
- array(
50
- 'get_callback' => array( 'Newspack_Blocks_API', 'newspack_blocks_get_author_info' ),
51
- 'schema' => array(
52
- 'context' => array(
53
- 'edit',
54
- ),
55
- 'type' => 'array',
56
- ),
57
- )
58
- );
59
-
60
- /* Add first category source */
61
- register_rest_field(
62
- 'post',
63
- 'newspack_category_info',
64
- array(
65
- 'get_callback' => array( 'Newspack_Blocks_API', 'newspack_blocks_get_primary_category' ),
66
- 'schema' => array(
67
- 'context' => array(
68
- 'edit',
69
- ),
70
- 'type' => 'string',
71
- ),
72
- )
73
- );
74
- }
75
-
76
- /**
77
- * Get thumbnail featured image source for the rest field.
78
- *
79
- * @param array $object The object info.
80
- * @return array | bool Featured image if available, false if not.
81
- */
82
- public static function newspack_blocks_get_image_src( $object ) {
83
- $featured_image_set = array();
84
-
85
- if ( 0 === $object['featured_media'] ) {
86
- return false;
87
- }
88
-
89
- // Landscape image.
90
- $landscape_size = Newspack_Blocks::image_size_for_orientation( 'landscape' );
91
-
92
- $feat_img_array_landscape = wp_get_attachment_image_src(
93
- $object['featured_media'],
94
- $landscape_size,
95
- false
96
- );
97
- $featured_image_set['landscape'] = $feat_img_array_landscape[0];
98
-
99
- // Portrait image.
100
- $portrait_size = Newspack_Blocks::image_size_for_orientation( 'portrait' );
101
-
102
- $feat_img_array_portrait = wp_get_attachment_image_src(
103
- $object['featured_media'],
104
- $portrait_size,
105
- false
106
- );
107
- $featured_image_set['portrait'] = $feat_img_array_portrait[0];
108
-
109
- // Square image.
110
- $square_size = Newspack_Blocks::image_size_for_orientation( 'square' );
111
-
112
- $feat_img_array_square = wp_get_attachment_image_src(
113
- $object['featured_media'],
114
- $square_size,
115
- false
116
- );
117
- $featured_image_set['square'] = $feat_img_array_square[0];
118
-
119
- // Uncropped image.
120
- $uncropped_size = 'newspack-article-block-uncropped';
121
-
122
- $feat_img_array_uncropped = wp_get_attachment_image_src(
123
- $object['featured_media'],
124
- $uncropped_size,
125
- false
126
- );
127
- $featured_image_set['uncropped'] = $feat_img_array_uncropped[0];
128
-
129
- return $featured_image_set;
130
- }
131
-
132
- /**
133
- * Get thumbnail featured image captions for the rest field.
134
- *
135
- * @param array $object The object info.
136
- * @return string|null Image caption on success, null on failure.
137
- */
138
- public static function newspack_blocks_get_image_caption( $object ) {
139
- return (int) $object['featured_media'] > 0 ? trim( wp_get_attachment_caption( $object['featured_media'] ) ) : null;
140
- }
141
-
142
- /**
143
- * Get author info for the rest field.
144
- *
145
- * @param array $object The object info.
146
- * @return array Author data.
147
- */
148
- public static function newspack_blocks_get_author_info( $object ) {
149
- $author_data = array();
150
-
151
- if ( function_exists( 'coauthors_posts_links' ) ) :
152
- $authors = get_coauthors();
153
-
154
- foreach ( $authors as $author ) {
155
- // Check if this is a guest author post type.
156
- if ( 'guest-author' === get_post_type( $author->ID ) ) {
157
- // If yes, make sure the author actually has an avatar set; otherwise, coauthors_get_avatar returns a featured image.
158
- if ( get_post_thumbnail_id( $author->ID ) ) {
159
- $author_avatar = coauthors_get_avatar( $author, 48 );
160
- } else {
161
- // If there is no avatar, force it to return the current fallback image.
162
- $author_avatar = get_avatar( ' ' );
163
- }
164
- } else {
165
- $author_avatar = coauthors_get_avatar( $author, 48 );
166
- }
167
- $author_data[] = array(
168
- /* Get the author name */
169
- 'display_name' => esc_html( $author->display_name ),
170
- /* Get the author avatar */
171
- 'avatar' => wp_kses_post( $author_avatar ),
172
- /* Get the author ID */
173
- 'id' => $author->ID,
174
- );
175
- }
176
- else :
177
- $author_data[] = array(
178
- /* Get the author name */
179
- 'display_name' => get_the_author_meta( 'display_name', $object['author'] ),
180
- /* Get the author avatar */
181
- 'avatar' => get_avatar( $object['author'], 48 ),
182
- /* Get the author ID */
183
- 'id' => $object['author'],
184
- );
185
- endif;
186
-
187
- /* Return the author data */
188
- return $author_data;
189
- }
190
-
191
- /**
192
- * Get primary category for the rest field.
193
- *
194
- * @param array $object The object info.
195
- * @return string Category name.
196
- */
197
- public static function newspack_blocks_get_primary_category( $object ) {
198
- $category = false;
199
-
200
- // Use Yoast primary category if set.
201
- if ( class_exists( 'WPSEO_Primary_Term' ) ) {
202
- $primary_term = new WPSEO_Primary_Term( 'category', $object['id'] );
203
- $category_id = $primary_term->get_primary_term();
204
- if ( $category_id ) {
205
- $category = get_term( $category_id );
206
- }
207
- }
208
-
209
- if ( ! $category ) {
210
- $categories_list = get_the_category( $object['id'] );
211
- if ( ! empty( $categories_list ) ) {
212
- $category = $categories_list[0];
213
- }
214
- }
215
-
216
- if ( ! $category ) {
217
- return '';
218
- }
219
-
220
- return $category->name;
221
- }
222
- }
223
-
224
- add_action( 'rest_api_init', array( 'Newspack_Blocks_API', 'register_rest_fields' ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/blog-posts-block/newspack-homepage-articles/class-newspack-blocks.php DELETED
@@ -1,407 +0,0 @@
1
- <?php
2
- /**
3
- * Newspack blocks functionality
4
- *
5
- * @package Newspack_Blocks
6
- */
7
-
8
- /**
9
- * Newspack blocks functionality
10
- */
11
- class Newspack_Blocks {
12
-
13
- /**
14
- * Add hooks and filters.
15
- */
16
- public static function init() {
17
- add_action( 'after_setup_theme', array( __CLASS__, 'add_image_sizes' ) );
18
- }
19
-
20
- /**
21
- * Gather dependencies and paths needed for script enqueuing.
22
- *
23
- * @param string $script_path Path to the script relative to plugin root.
24
- *
25
- * @return array Associative array including dependency array, version, and web path to the script. Returns false if script doesn't exist.
26
- */
27
- public static function script_enqueue_helper( $script_path ) {
28
- $local_path = NEWSPACK_BLOCKS__PLUGIN_DIR . $script_path;
29
- if ( ! file_exists( $local_path ) ) {
30
- return false;
31
- }
32
-
33
- $path_info = pathinfo( $local_path );
34
- $asset_path = $path_info['dirname'] . '/' . $path_info['filename'] . '.asset.php';
35
- $script_data = file_exists( $asset_path )
36
- ? require $asset_path
37
- : array(
38
- 'dependencies' => array(),
39
- 'version' => filemtime( $local_path ),
40
- );
41
-
42
- $script_data['script_path'] = plugins_url( $script_path, __FILE__ );
43
- return $script_data;
44
- }
45
-
46
- /**
47
- * Enqueue block scripts and styles for editor.
48
- */
49
- public static function enqueue_block_editor_assets() {
50
- $script_data = static::script_enqueue_helper( NEWSPACK_BLOCKS__BLOCKS_DIRECTORY . 'editor.js' );
51
-
52
- if ( $script_data ) {
53
- wp_enqueue_script(
54
- 'newspack-blocks-editor',
55
- $script_data['script_path'],
56
- $script_data['dependencies'],
57
- $script_data['version'],
58
- true
59
- );
60
- }
61
-
62
- $editor_style = plugins_url( NEWSPACK_BLOCKS__BLOCKS_DIRECTORY . 'editor.css', __FILE__ );
63
-
64
- wp_enqueue_style(
65
- 'newspack-blocks-editor',
66
- $editor_style,
67
- array(),
68
- NEWSPACK_BLOCKS__VERSION
69
- );
70
-
71
- wp_set_script_translations(
72
- 'newspack-blocks-editor',
73
- 'newspack-blocks',
74
- plugin_dir_path( __FILE__ ) . 'languages'
75
- );
76
- }
77
-
78
- /**
79
- * Enqueue block scripts and styles for view.
80
- */
81
- public static function manage_view_scripts() {
82
- if ( is_admin() ) {
83
- // In editor environment, do nothing.
84
- return;
85
- }
86
- $src_directory = NEWSPACK_BLOCKS__PLUGIN_DIR . 'src/blocks/';
87
- $dist_directory = NEWSPACK_BLOCKS__PLUGIN_DIR . 'dist/';
88
- $iterator = new DirectoryIterator( $src_directory );
89
- foreach ( $iterator as $block_directory ) {
90
- if ( ! $block_directory->isDir() || $block_directory->isDot() ) {
91
- continue;
92
- }
93
- $type = $block_directory->getFilename();
94
-
95
- /* If view.php is found, include it and use for block rendering. */
96
- $view_php_path = $src_directory . $type . '/view.php';
97
- if ( file_exists( $view_php_path ) ) {
98
- include_once $view_php_path;
99
- continue;
100
- }
101
-
102
- /* If view.php is missing but view Javascript file is found, do generic view asset loading. */
103
- $view_js_path = $dist_directory . $type . '/view.js';
104
- if ( file_exists( $view_js_path ) ) {
105
- register_block_type(
106
- "newspack-blocks/{$type}",
107
- array(
108
- 'render_callback' => function( $attributes, $content ) use ( $type ) {
109
- Newspack_Blocks::enqueue_view_assets( $type );
110
- return $content;
111
- },
112
- )
113
- );
114
- }
115
- }
116
- }
117
-
118
- /**
119
- * Enqueue block styles stylesheet.
120
- */
121
- public static function enqueue_block_styles_assets() {
122
- $style_path = NEWSPACK_BLOCKS__BLOCKS_DIRECTORY . 'block_styles' . ( is_rtl() ? '.rtl' : '' ) . '.css';
123
- if ( file_exists( NEWSPACK_BLOCKS__PLUGIN_DIR . $style_path ) ) {
124
- wp_enqueue_style(
125
- 'newspack-blocks-block-styles-stylesheet',
126
- plugins_url( $style_path, __FILE__ ),
127
- array(),
128
- NEWSPACK_BLOCKS__VERSION
129
- );
130
- }
131
- }
132
-
133
- /**
134
- * Enqueue view scripts and styles for a single block.
135
- *
136
- * @param string $type The block's type.
137
- */
138
- public static function enqueue_view_assets( $type ) {
139
- $style_path = apply_filters(
140
- 'newspack_blocks_enqueue_view_assets',
141
- NEWSPACK_BLOCKS__BLOCKS_DIRECTORY . $type . '/view' . ( is_rtl() ? '.rtl' : '' ) . '.css',
142
- $type,
143
- is_rtl()
144
- );
145
-
146
- if ( file_exists( NEWSPACK_BLOCKS__PLUGIN_DIR . $style_path ) ) {
147
- wp_enqueue_style(
148
- "newspack-blocks-{$type}",
149
- plugins_url( $style_path, __FILE__ ),
150
- array(),
151
- NEWSPACK_BLOCKS__VERSION
152
- );
153
- }
154
- if ( static::is_amp() ) {
155
- return;
156
- }
157
- $script_data = static::script_enqueue_helper( NEWSPACK_BLOCKS__BLOCKS_DIRECTORY . $type . '/view.js' );
158
- if ( $script_data ) {
159
- wp_enqueue_script(
160
- "newspack-blocks-{$type}",
161
- $script_data['script_path'],
162
- $script_data['dependencies'],
163
- $script_data['version'],
164
- true
165
- );
166
- }
167
- }
168
-
169
- /**
170
- * Utility to assemble the class for a server-side rendered block.
171
- *
172
- * @param string $type The block type.
173
- * @param array $attributes Block attributes.
174
- * @param array $extra Additional classes to be added to the class list.
175
- *
176
- * @return string Class list separated by spaces.
177
- */
178
- public static function block_classes( $type, $attributes = array(), $extra = array() ) {
179
- $classes = array( "wp-block-newspack-blocks-{$type}" );
180
-
181
- if ( ! empty( $attributes['align'] ) ) {
182
- $classes[] = 'align' . $attributes['align'];
183
- }
184
- if ( isset( $attributes['className'] ) ) {
185
- array_push( $classes, $attributes['className'] );
186
- }
187
- if ( is_array( $extra ) && ! empty( $extra ) ) {
188
- $classes = array_merge( $classes, $extra );
189
- }
190
-
191
- return implode( $classes, ' ' );
192
- }
193
-
194
- /**
195
- * Checks whether the current view is served in AMP context.
196
- *
197
- * @return bool True if AMP, false otherwise.
198
- */
199
- public static function is_amp() {
200
- return ! is_admin() && function_exists( 'is_amp_endpoint' ) && is_amp_endpoint();
201
- }
202
-
203
- /**
204
- * Return the most appropriate thumbnail size to display.
205
- *
206
- * @param string $orientation The block's orientation settings: landscape|portrait|square.
207
- *
208
- * @return string Returns the thumbnail key to use.
209
- */
210
- public static function image_size_for_orientation( $orientation = 'landscape' ) {
211
- $sizes = array(
212
- 'landscape' => array(
213
- 'large' => array(
214
- 1200,
215
- 900,
216
- ),
217
- 'medium' => array(
218
- 800,
219
- 600,
220
- ),
221
- 'small' => array(
222
- 400,
223
- 300,
224
- ),
225
- 'tiny' => array(
226
- 200,
227
- 150,
228
- ),
229
- ),
230
- 'portrait' => array(
231
- 'large' => array(
232
- 900,
233
- 1200,
234
- ),
235
- 'medium' => array(
236
- 600,
237
- 800,
238
- ),
239
- 'small' => array(
240
- 300,
241
- 400,
242
- ),
243
- 'tiny' => array(
244
- 150,
245
- 200,
246
- ),
247
- ),
248
- 'square' => array(
249
- 'large' => array(
250
- 1200,
251
- 1200,
252
- ),
253
- 'medium' => array(
254
- 800,
255
- 800,
256
- ),
257
- 'small' => array(
258
- 400,
259
- 400,
260
- ),
261
- 'tiny' => array(
262
- 200,
263
- 200,
264
- ),
265
- ),
266
- );
267
-
268
- foreach ( $sizes[ $orientation ] as $key => $dimensions ) {
269
- $attachment = wp_get_attachment_image_src(
270
- get_post_thumbnail_id( get_the_ID() ),
271
- 'newspack-article-block-' . $orientation . '-' . $key
272
- );
273
- if ( $dimensions[0] === $attachment[1] && $dimensions[1] === $attachment[2] ) {
274
- return 'newspack-article-block-' . $orientation . '-' . $key;
275
- }
276
- }
277
-
278
- return 'large';
279
- }
280
-
281
- /**
282
- * Registers image sizes required for Newspack Blocks.
283
- */
284
- public static function add_image_sizes() {
285
- add_image_size( 'newspack-article-block-landscape-large', 1200, 900, true );
286
- add_image_size( 'newspack-article-block-portrait-large', 900, 1200, true );
287
- add_image_size( 'newspack-article-block-square-large', 1200, 1200, true );
288
-
289
- add_image_size( 'newspack-article-block-landscape-medium', 800, 600, true );
290
- add_image_size( 'newspack-article-block-portrait-medium', 600, 800, true );
291
- add_image_size( 'newspack-article-block-square-medium', 800, 800, true );
292
-
293
- add_image_size( 'newspack-article-block-landscape-small', 400, 300, true );
294
- add_image_size( 'newspack-article-block-portrait-small', 300, 400, true );
295
- add_image_size( 'newspack-article-block-square-small', 400, 400, true );
296
-
297
- add_image_size( 'newspack-article-block-landscape-tiny', 200, 150, true );
298
- add_image_size( 'newspack-article-block-portrait-tiny', 150, 200, true );
299
- add_image_size( 'newspack-article-block-square-tiny', 200, 200, true );
300
-
301
- add_image_size( 'newspack-article-block-uncropped', 1200, 9999, false );
302
- }
303
-
304
- /**
305
- * Builds and returns query args based on block attributes.
306
- *
307
- * @param array $attributes An array of block attributes.
308
- *
309
- * @return array
310
- */
311
- public static function build_articles_query( $attributes ) {
312
- global $newspack_blocks_post_id;
313
- if ( ! $newspack_blocks_post_id ) {
314
- $newspack_blocks_post_id = array();
315
- }
316
- $authors = isset( $attributes['authors'] ) ? $attributes['authors'] : array();
317
- $categories = isset( $attributes['categories'] ) ? $attributes['categories'] : array();
318
- $tags = isset( $attributes['tags'] ) ? $attributes['tags'] : array();
319
- $tag_exclusions = isset( $attributes['tagExclusions'] ) ? $attributes['tagExclusions'] : array();
320
- $specific_posts = isset( $attributes['specificPosts'] ) ? $attributes['specificPosts'] : array();
321
- $posts_to_show = intval( $attributes['postsToShow'] );
322
- $specific_mode = intval( $attributes['specificMode'] );
323
- $args = array(
324
- 'post_status' => 'publish',
325
- 'suppress_filters' => false,
326
- 'ignore_sticky_posts' => true,
327
- );
328
- if ( $specific_mode && $specific_posts ) {
329
- $args['post__in'] = $specific_posts;
330
- $args['orderby'] = 'post__in';
331
- } else {
332
- $args['posts_per_page'] = $posts_to_show + count( $newspack_blocks_post_id );
333
- if ( $authors && count( $authors ) ) {
334
- $args['author__in'] = $authors;
335
- }
336
- if ( $categories && count( $categories ) ) {
337
- $args['category__in'] = $categories;
338
- }
339
- if ( $tags && count( $tags ) ) {
340
- $args['tag__in'] = $tags;
341
- }
342
- if ( $tag_exclusions && count( $tag_exclusions ) ) {
343
- $args['tag__not_in'] = $tag_exclusions;
344
- }
345
- }
346
- return $args;
347
- }
348
-
349
- /**
350
- * Loads a template with given data in scope.
351
- *
352
- * @param string $template full Path to the template to be included.
353
- * @param array $data Data to be passed into the template to be included.
354
- * @return string
355
- */
356
- public static function template_inc( $template, $data = array() ) {
357
- if ( ! strpos( $template, '.php' ) ) {
358
- $template = $template . '.php';
359
- }
360
- if ( ! is_file( $template ) ) {
361
- return '';
362
- }
363
- ob_start();
364
- include $template;
365
- $contents = ob_get_contents();
366
- ob_end_clean();
367
- return $contents;
368
- }
369
-
370
- /**
371
- * Prepare an array of authors, taking presence of CoAuthors Plus into account.
372
- *
373
- * @return array Array of WP_User objects.
374
- */
375
- public static function prepare_authors() {
376
- if ( function_exists( 'coauthors_posts_links' ) ) {
377
- $authors = get_coauthors();
378
- foreach ( $authors as $author ) {
379
- // Check if this is a guest author post type.
380
- if ( 'guest-author' === get_post_type( $author->ID ) ) {
381
- // If yes, make sure the author actually has an avatar set; otherwise, coauthors_get_avatar returns a featured image.
382
- if ( get_post_thumbnail_id( $author->ID ) ) {
383
- $author->avatar = coauthors_get_avatar( $author, 48 );
384
- } else {
385
- // If there is no avatar, force it to return the current fallback image.
386
- $author->avatar = get_avatar( ' ' );
387
- }
388
- } else {
389
- $author->avatar = coauthors_get_avatar( $author, 48 );
390
- }
391
- $author->url = get_author_posts_url( $author->ID, $author->user_nicename );
392
- }
393
- return $authors;
394
- }
395
- $id = get_the_author_meta( 'ID' );
396
- return array(
397
- (object) array(
398
- 'ID' => $id,
399
- 'avatar' => get_avatar( $id, 48 ),
400
- 'url' => get_author_posts_url( $id ),
401
- 'user_nicename' => get_the_author(),
402
- 'display_name' => get_the_author_meta( 'display_name' ),
403
- ),
404
- );
405
- }
406
- }
407
- Newspack_Blocks::init();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/blog-posts-block/newspack-homepage-articles/components/autocomplete-tokenfield.js DELETED
@@ -1,175 +0,0 @@
1
- /**
2
- * External dependencies
3
- */
4
- import { debounce } from 'lodash';
5
-
6
- /**
7
- * WordPress dependencies
8
- */
9
- import { Component } from '@wordpress/element';
10
- import { FormTokenField, Spinner } from '@wordpress/components';
11
-
12
- /**
13
- * Internal dependencies
14
- */
15
- import './autocomplete-tokenfield.scss';
16
-
17
- /**
18
- * An multi-selecting, api-driven autocomplete input suitable for use in block attributes.
19
- */
20
- class AutocompleteTokenField extends Component {
21
- constructor( props ) {
22
- super( props );
23
- this.state = {
24
- suggestions: [],
25
- validValues: {},
26
- loading: false,
27
- };
28
-
29
- this.debouncedUpdateSuggestions = debounce( this.updateSuggestions, 500 )
30
- }
31
-
32
- /**
33
- * When the component loads, fetch information about the tokens so we can populate
34
- * the tokens with the correct labels.
35
- */
36
- componentDidMount() {
37
- const { tokens, fetchSavedInfo } = this.props;
38
-
39
- if ( ! tokens.length || ! fetchSavedInfo ) {
40
- return;
41
- }
42
-
43
- this.setState( { loading: true }, () => {
44
- fetchSavedInfo( tokens )
45
- .then( results => {
46
- const { validValues } = this.state;
47
-
48
- results.forEach( suggestion => {
49
- validValues[ suggestion.value ] = suggestion.label;
50
- } );
51
-
52
- this.setState( { validValues, loading: false } );
53
- } );
54
- } );
55
- }
56
-
57
- /**
58
- * Clean up any unfinished autocomplete api call requests.
59
- */
60
- componentWillUnmount() {
61
- delete this.suggestionsRequest;
62
- this.debouncedUpdateSuggestions.cancel();
63
- }
64
-
65
- /**
66
- * Get a list of labels for input values.
67
- *
68
- * @param array values Array of values (ids, etc.).
69
- * @return array Array of valid labels corresponding to the values.
70
- */
71
- getLabelsForValues( values ) {
72
- const { validValues } = this.state;
73
- return values.reduce(
74
- ( accumulator, value ) =>
75
- validValues[ value ] ? [ ...accumulator, validValues[ value ] ] : accumulator,
76
- []
77
- );
78
- }
79
-
80
- /**
81
- * Get a list of values for input labels.
82
- *
83
- * @param array labels Array of labels from the tokens.
84
- * @return array Array of valid values corresponding to the labels.
85
- */
86
- getValuesForLabels( labels ) {
87
- const { validValues } = this.state;
88
- return labels.map( label =>
89
- Object.keys( validValues ).find( key => validValues[ key ] === label )
90
- );
91
- }
92
-
93
- /**
94
- * Refresh the autocomplete dropdown.
95
- */
96
- updateSuggestions( input ) {
97
- const { fetchSuggestions } = this.props;
98
- if ( ! fetchSuggestions ) {
99
- return;
100
- }
101
-
102
- this.setState( { loading: true }, () => {
103
- const request = fetchSuggestions( input );
104
- request.then( suggestions => {
105
- // A fetch Promise doesn't have an abort option. It's mimicked by
106
- // comparing the request reference in on the instance, which is
107
- // reset or deleted on subsequent requests or unmounting.
108
- if ( this.suggestionsRequest !== request ) {
109
- return;
110
- }
111
-
112
- const { validValues } = this.state;
113
- const currentSuggestions = []
114
-
115
- suggestions.forEach( suggestion => {
116
- currentSuggestions.push( suggestion.label );
117
- validValues[ suggestion.value ] = suggestion.label;
118
- } );
119
-
120
- this.setState( { suggestions: currentSuggestions, validValues, loading: false } );
121
- } ).catch( () => {
122
- if ( this.suggestionsRequest === request ) {
123
- this.setState( {
124
- loading: false,
125
- } );
126
- }
127
- } );
128
-
129
- this.suggestionsRequest = request;
130
- } );
131
- }
132
-
133
- /**
134
- * When a token is selected, we need to convert the string label into a recognized value suitable for saving as an attribute.
135
- *
136
- * @param array tokenStrings An array of token label strings.
137
- */
138
- handleOnChange( tokenStrings ) {
139
- const { onChange } = this.props;
140
- onChange( this.getValuesForLabels( tokenStrings ) );
141
- }
142
-
143
- /**
144
- * To populate the tokens, we need to convert the values into a human-readable label.
145
- *
146
- * @return array An array of token label strings.
147
- */
148
- getTokens() {
149
- const { tokens } = this.props;
150
- return this.getLabelsForValues( tokens );
151
- }
152
-
153
- /**
154
- * Render.
155
- */
156
- render() {
157
- const { label = '' } = this.props;
158
- const { suggestions, loading } = this.state;
159
-
160
- return (
161
- <div className='autocomplete-tokenfield'>
162
- <FormTokenField
163
- value={ this.getTokens() }
164
- suggestions={ suggestions }
165
- onChange={ tokens => this.handleOnChange( tokens ) }
166
- onInputChange={ input => this.debouncedUpdateSuggestions( input ) }
167
- label={ label }
168
- />
169
- { loading && <Spinner /> }
170
- </div>
171
- );
172
- }
173
- }
174
-
175
- export default AutocompleteTokenField;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/blog-posts-block/newspack-homepage-articles/components/autocomplete-tokenfield.scss DELETED
@@ -1,9 +0,0 @@
1
- .autocomplete-tokenfield {
2
- position: relative;
3
-
4
- .components-spinner {
5
- position: absolute;
6
- top: 2em;
7
- right: 0;
8
- }
9
- }
 
 
 
 
 
 
 
 
 
trunk/blog-posts-block/newspack-homepage-articles/components/query-controls.js DELETED
@@ -1,254 +0,0 @@
1
- /**
2
- * WordPress dependencies
3
- */
4
- import { __ } from '@wordpress/i18n';
5
- import { Component, Fragment } from '@wordpress/element';
6
- import {
7
- Button,
8
- QueryControls as BaseControl,
9
- SelectControl,
10
- ToggleControl,
11
- } from '@wordpress/components';
12
- import apiFetch from '@wordpress/api-fetch';
13
- import { addQueryArgs } from '@wordpress/url';
14
- import { decodeEntities } from '@wordpress/html-entities';
15
-
16
- /**
17
- * Internal dependencies.
18
- */
19
- import AutocompleteTokenField from './autocomplete-tokenfield';
20
-
21
- class QueryControls extends Component {
22
- state = {
23
- showAdvancedFilters: false,
24
- };
25
-
26
- fetchPostSuggestions = search => {
27
- return apiFetch( {
28
- path: addQueryArgs( '/wp/v2/search', {
29
- search,
30
- per_page: 20,
31
- _fields: 'id,title',
32
- type: 'post',
33
- } ),
34
- } ).then( function( posts ) {
35
- const result = posts.map( post => ( {
36
- value: post.id,
37
- label: decodeEntities( post.title ) || __( '(no title)', 'newspack-blocks' ),
38
- } ) );
39
- return result;
40
- } );
41
- };
42
- fetchSavedPosts = postIDs => {
43
- return apiFetch( {
44
- path: addQueryArgs( '/wp/v2/posts', {
45
- per_page: 100,
46
- include: postIDs.join( ',' ),
47
- _fields: 'id,title',
48
- } ),
49
- } ).then( function( posts ) {
50
- return posts.map( post => ( {
51
- value: post.id,
52
- label: decodeEntities( post.title.rendered ) || __( '(no title)', 'newspack-blocks' ),
53
- } ) );
54
- } );
55
- };
56
-
57
- fetchAuthorSuggestions = search => {
58
- return apiFetch( {
59
- path: addQueryArgs( '/wp/v2/users', {
60
- search,
61
- per_page: 20,
62
- _fields: 'id,name',
63
- } ),
64
- } ).then( function( users ) {
65
- return users.map( user => ( {
66
- value: user.id,
67
- label: decodeEntities( user.name ) || __( '(no name)', 'newspack-blocks' ),
68
- } ) );
69
- } );
70
- };
71
- fetchSavedAuthors = userIDs => {
72
- return apiFetch( {
73
- path: addQueryArgs( '/wp/v2/users', {
74
- per_page: 100,
75
- include: userIDs.join( ',' ),
76
- _fields: 'id,name',
77
- } ),
78
- } ).then( function( users ) {
79
- return users.map( user => ( {
80
- value: user.id,
81
- label: decodeEntities( user.name ) || __( '(no name)', 'newspack-blocks' ),
82
- } ) );
83
- } );
84
- };
85
-
86
- fetchCategorySuggestions = search => {
87
- return apiFetch( {
88
- path: addQueryArgs( '/wp/v2/categories', {
89
- search,
90
- per_page: 20,
91
- _fields: 'id,name',
92
- orderby: 'count',
93
- order: 'desc',
94
- } ),
95
- } ).then( function( categories ) {
96
- return categories.map( category => ( {
97
- value: category.id,
98
- label: decodeEntities( category.name ) || __( '(no title)', 'newspack-blocks' ),
99
- } ) );
100
- } );
101
- };
102
- fetchSavedCategories = categoryIDs => {
103
- return apiFetch( {
104
- path: addQueryArgs( '/wp/v2/categories', {
105
- per_page: 100,
106
- _fields: 'id,name',
107
- include: categoryIDs.join( ',' ),
108
- } ),
109
- } ).then( function( categories ) {
110
- return categories.map( category => ( {
111
- value: category.id,
112
- label: decodeEntities( category.name ) || __( '(no title)', 'newspack-blocks' ),
113
- } ) );
114
- } );
115
- };
116
-
117
- fetchTagSuggestions = search => {
118
- return apiFetch( {
119
- path: addQueryArgs( '/wp/v2/tags', {
120
- search,
121
- per_page: 20,
122
- _fields: 'id,name',
123
- orderby: 'count',
124
- order: 'desc',
125
- } ),
126
- } ).then( function( tags ) {
127
- return tags.map( tag => ( {
128
- value: tag.id,
129
- label: decodeEntities( tag.name ) || __( '(no title)', 'newspack-blocks' ),
130
- } ) );
131
- } );
132
- };
133
- fetchSavedTags = tagIDs => {
134
- return apiFetch( {
135
- path: addQueryArgs( '/wp/v2/tags', {
136
- per_page: 100,
137
- _fields: 'id,name',
138
- include: tagIDs.join( ',' ),
139
- } ),
140
- } ).then( function( tags ) {
141
- return tags.map( tag => ( {
142
- value: tag.id,
143
- label: decodeEntities( tag.name ) || __( '(no title)', 'newspack-blocks' ),
144
- } ) );
145
- } );
146
- };
147
-
148
- render = () => {
149
- const {
150
- numberOfItems,
151
- onNumberOfItemsChange,
152
- specificMode,
153
- onSpecificModeChange,
154
- specificPosts,
155
- onSpecificPostsChange,
156
- authors,
157
- onAuthorsChange,
158
- categories,
159
- onCategoriesChange,
160
- tags,
161
- onTagsChange,
162
- tagExclusions,
163
- onTagExclusionsChange,
164
- enableSpecific,
165
- } = this.props;
166
- const { showAdvancedFilters } = this.state;
167
-
168
- return [
169
- enableSpecific && (
170
- <ToggleControl
171
- key="specificMode"
172
- checked={ specificMode }
173
- onChange={ onSpecificModeChange }
174
- label={ __( 'Choose specific stories', 'newspack-blocks' ) }
175
- />
176
- ),
177
- specificMode && (
178
- <AutocompleteTokenField
179
- key="posts"
180
- tokens={ specificPosts || [] }
181
- onChange={ onSpecificPostsChange }
182
- fetchSuggestions={ this.fetchPostSuggestions }
183
- fetchSavedInfo={ this.fetchSavedPosts }
184
- label={ __( 'Posts', 'newspack-blocks' ) }
185
- />
186
- ),
187
- ! specificMode && <BaseControl key="queryControls" { ...this.props } />,
188
- ! specificMode && onAuthorsChange && (
189
- <AutocompleteTokenField
190
- key="authors"
191
- tokens={ authors || [] }
192
- onChange={ onAuthorsChange }
193
- fetchSuggestions={ this.fetchAuthorSuggestions }
194
- fetchSavedInfo={ this.fetchSavedAuthors }
195
- label={ __( 'Authors', 'newspack-blocks' ) }
196
- />
197
- ),
198
- ! specificMode && onCategoriesChange && (
199
- <AutocompleteTokenField
200
- key="categories"
201
- tokens={ categories || [] }
202
- onChange={ onCategoriesChange }
203
- fetchSuggestions={ this.fetchCategorySuggestions }
204
- fetchSavedInfo={ this.fetchSavedCategories }
205
- label={ __( 'Categories', 'newspack-blocks' ) }
206
- />
207
- ),
208
- ! specificMode && onTagsChange && (
209
- <AutocompleteTokenField
210
- key="tags"
211
- tokens={ tags || [] }
212
- onChange={ onTagsChange }
213
- fetchSuggestions={ this.fetchTagSuggestions }
214
- fetchSavedInfo={ this.fetchSavedTags }
215
- label={ __( 'Tags', 'newspack-blocks' ) }
216
- />
217
- ),
218
- ! specificMode && onTagExclusionsChange && (
219
- <p>
220
- <Button
221
- key="toggle-advanced-filters"
222
- isLink
223
- onClick={ () => this.setState( { showAdvancedFilters: ! showAdvancedFilters } ) }
224
- >
225
- { showAdvancedFilters
226
- ? __( 'Hide Advanced Filters', 'newspack-blocks' )
227
- : __( 'Show Advanced Filters', 'newspack-blocks' ) }
228
- </Button>
229
- </p>
230
- ),
231
- ! specificMode && onTagExclusionsChange && showAdvancedFilters && (
232
- <AutocompleteTokenField
233
- key="tag-exclusion"
234
- tokens={ tagExclusions || [] }
235
- onChange={ onTagExclusionsChange }
236
- fetchSuggestions={ this.fetchTagSuggestions }
237
- fetchSavedInfo={ this.fetchSavedTags }
238
- label={ __( 'Excluded Tags', 'newspack-blocks' ) }
239
- />
240
- ),
241
- ];
242
- };
243
- }
244
-
245
- QueryControls.defaultProps = {
246
- enableSpecific: true,
247
- specificPosts: [],
248
- authors: [],
249
- categories: [],
250
- tags: [],
251
- tagExclusions: [],
252
- };
253
-
254
- export default QueryControls;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/blog-posts-block/newspack-homepage-articles/shared/sass/_colors.scss DELETED
@@ -1,8 +0,0 @@
1
- $color__primary: #36f;
2
- $color__background-body: #fff;
3
- $color__background-input: #fff;
4
- $color__background-screen: #f1f1f1;
5
- $color__text-main: #111;
6
- $color__text-light: #767676;
7
- $color__text-input-focus: #111;
8
- $color__border: #ccc;
 
 
 
 
 
 
 
 
trunk/blog-posts-block/newspack-homepage-articles/shared/sass/_legacy_colors.scss DELETED
@@ -1,13 +0,0 @@
1
- $muriel-white: #fff;
2
-
3
- $muriel-gray-0: #f6f6f6;
4
- $muriel-gray-50: #e1e2e2;
5
- $muriel-gray-100: #ccced0;
6
- $muriel-gray-200: #b0b5b8;
7
- $muriel-gray-300: #969ca1;
8
- $muriel-gray-400: #7c848b;
9
- $muriel-gray-500: #636d75;
10
- $muriel-gray-600: #50575d;
11
- $muriel-gray-700: #3d4145;
12
- $muriel-gray-800: #2b2d2f;
13
- $muriel-gray-900: #1a1a1a;
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/blog-posts-block/newspack-homepage-articles/shared/sass/_mixins.scss DELETED
@@ -1,26 +0,0 @@
1
-
2
- @mixin media( $res ) {
3
- @if mobile == $res {
4
- @media only screen and (min-width: $mobile_width) {
5
- @content;
6
- }
7
- }
8
-
9
- @if tablet == $res {
10
- @media only screen and (min-width: $tablet_width) {
11
- @content;
12
- }
13
- }
14
-
15
- @if desktop == $res {
16
- @media only screen and (min-width: $desktop_width) {
17
- @content;
18
- }
19
- }
20
-
21
- @if wide == $res {
22
- @media only screen and (min-width: $wide_width) {
23
- @content;
24
- }
25
- }
26
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/blog-posts-block/newspack-homepage-articles/shared/sass/_variables.scss DELETED
@@ -1,27 +0,0 @@
1
- $mobile_width: 600px;
2
- $tablet_width: 782px;
3
- $desktop_width: 1168px;
4
- $wide_width: 1379px;
5
-
6
- $font__size_base: 20px;
7
- $font__size-ratio: 1.125;
8
-
9
- $font__size-xxxs: 1em * 0.5; // 10px
10
- $font__size-xxs: 1em * 0.6; // 12px
11
- $font__size-xs: 1em * 0.7; // 14px
12
- $font__size-sm: 1em * 0.8; // 16px
13
- // $font__size_base: 1em * 1; // 20px
14
- $font__size-md: 1em * 1.2; // 24px
15
- $font__size-lg: 1em * 1.4; // 28px
16
- $font__size-xl: 1em * 1.8; // 36px
17
- $font__size-xxl: 1em * 2.2; // 44px
18
- $font__size-xxxl: 1em * 2.8; // 56px
19
- $font__size-xxxxl: 1em * 3.2; // 64px
20
-
21
-
22
- $font__line-height-body: 1.6;
23
- $font__line-height-pre: 1.6;
24
- $font__line-height-heading: 1.2;
25
- $font__line-height-double: 2 * $font__line-height-heading;
26
-
27
- $color__border: #ccc;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/blog-posts-block/view.js DELETED
@@ -1 +0,0 @@
1
- import './newspack-homepage-articles/blocks/homepage-articles/view';
 
trunk/full-site-editing-plugin.php DELETED
@@ -1,213 +0,0 @@
1
- <?php
2
- /**
3
- * Plugin Name: Full Site Editing
4
- * Description: Enhances your page creation workflow within the Block Editor.
5
- * Version: 0.18
6
- * Author: Automattic
7
- * Author URI: https://automattic.com/wordpress-plugins/
8
- * License: GPLv2 or later
9
- * Text Domain: full-site-editing
10
- *
11
- * @package A8C\FSE
12
- */
13
-
14
- namespace A8C\FSE;
15
-
16
- /**
17
- * This file should only be used to load files needed for each subfeature.
18
- *
19
- * For example, if you are adding a new feature to this plugin called "Foo",
20
- * you would create a directory `./foo` to contain all code needed by your
21
- * feature. Then, in this file, you would add a `load_foo()` function which
22
- * includes your feature's files via the 'plugins_loaded' action.
23
- *
24
- * Please take care to _not_ load your feature's files if there are situations
25
- * which could cause bugs. For example, FSE files are only loaded if FSE is
26
- * active on the site.
27
- *
28
- * Finally, don't forget to use the A8C\FSE namespace for your code. :)
29
- */
30
-
31
- /**
32
- * Plugin version.
33
- *
34
- * Can be used in cache keys to invalidate caches on plugin update.
35
- *
36
- * @var string
37
- */
38
- define( 'PLUGIN_VERSION', '0.18' );
39
-
40
- // Always include these helper files for FSE.
41
- require_once __DIR__ . '/full-site-editing/helpers.php';
42
-
43
- /**
44
- * Load Full Site Editing.
45
- */
46
- function load_full_site_editing() {
47
- // Bail if FSE should not be active on the site. We do not
48
- // want to load FSE functionality on non-supported sites!
49
- if ( ! is_full_site_editing_active() ) {
50
- return;
51
- }
52
- // Not dangerous here since we have already checked for eligibility.
53
- dangerously_load_full_site_editing_files();
54
- Full_Site_Editing::get_instance();
55
- }
56
- add_action( 'plugins_loaded', __NAMESPACE__ . '\load_full_site_editing' );
57
-
58
- /**
59
- * Load Posts List Block.
60
- */
61
- function load_posts_list_block() {
62
- if ( class_exists( 'Posts_List_Block' ) ) {
63
- return;
64
- }
65
-
66
- /**
67
- * Can be used to disable the Post List Block.
68
- *
69
- * @since 0.2
70
- *
71
- * @param bool true if Post List Block should be disabled, false otherwise.
72
- */
73
- if ( apply_filters( 'a8c_disable_post_list_block', false ) ) {
74
- return;
75
- }
76
-
77
- require_once __DIR__ . '/posts-list-block/utils.php';
78
- require_once __DIR__ . '/posts-list-block/class-posts-list-block.php';
79
-
80
- Posts_List_Block::get_instance();
81
- }
82
- add_action( 'plugins_loaded', __NAMESPACE__ . '\load_posts_list_block' );
83
-
84
- /**
85
- * Load Starter_Page_Templates.
86
- */
87
- function load_starter_page_templates() {
88
- // We don't want the user to choose a template when copying a post.
89
- // phpcs:ignore WordPress.Security.NonceVerification.Recommended
90
- if ( isset( $_GET['jetpack-copy'] ) ) {
91
- return;
92
- }
93
-
94
- /**
95
- * Can be used to disable the Starter Page Templates.
96
- *
97
- * @since 0.2
98
- *
99
- * @param bool true if Starter Page Templates should be disabled, false otherwise.
100
- */
101
- if ( apply_filters( 'a8c_disable_starter_page_templates', false ) ) {
102
- return;
103
- }
104
-
105
- require_once __DIR__ . '/starter-page-templates/class-starter-page-templates.php';
106
-
107
- Starter_Page_Templates::get_instance();
108
- }
109
- add_action( 'plugins_loaded', __NAMESPACE__ . '\load_starter_page_templates' );
110
-
111
- /**
112
- * Load Global Styles plugin.
113
- */
114
- function load_global_styles() {
115
- require_once __DIR__ . '/global-styles/class-global-styles.php';
116
- }
117
- add_action( 'plugins_loaded', __NAMESPACE__ . '\load_global_styles' );
118
-
119
- /**
120
- * Load Event Countdown Block
121
- */
122
- add_action(
123
- 'plugins_loaded',
124
- function() {
125
- require_once __DIR__ . '/event-countdown-block/index.php';
126
- }
127
- );
128
-
129
- /**
130
- * Load Timeline Block
131
- */
132
- add_action(
133
- 'plugins_loaded',
134
- function() {
135
- require_once __DIR__ . '/jetpack-timeline/index.php';
136
- }
137
- );
138
-
139
- /**
140
- * Add front-end CoBlocks gallery block scripts.
141
- *
142
- * This function performs the same enqueueing duties as `CoBlocks_Block_Assets::frontend_scripts`,
143
- * but for our FSE header and footer content. `frontend_scripts` uses `has_block` to determine
144
- * if gallery blocks are present, and `has_block` is not aware of content sections outside of
145
- * post_content yet.
146
- */
147
- function enqueue_coblocks_gallery_scripts() {
148
- if ( ! function_exists( 'CoBlocks' ) || ! is_full_site_editing_active() ) {
149
- return;
150
- }
151
-
152
- // This happens in the Customizer because we try very hard not to load things and we get a fatal
153
- // https://github.com/Automattic/wp-calypso/issues/36680.
154
- if ( ! class_exists( '\A8C\FSE\WP_Template' ) ) {
155
- require_once __DIR__ . '/full-site-editing/templates/class-wp-template.php';
156
- }
157
- $template = new WP_Template();
158
- $header = $template->get_template_content( 'header' );
159
- $footer = $template->get_template_content( 'footer' );
160
-
161
- // Define where the asset is loaded from.
162
- $dir = CoBlocks()->asset_source( 'js' );
163
-
164
- // Define where the vendor asset is loaded from.
165
- $vendors_dir = CoBlocks()->asset_source( 'js', 'vendors' );
166
-
167
- // Masonry block.
168
- if ( has_block( 'coblocks/gallery-masonry', $header . $footer ) ) {
169
- wp_enqueue_script(
170
- 'coblocks-masonry',
171
- $dir . 'coblocks-masonry' . COBLOCKS_ASSET_SUFFIX . '.js',
172
- array( 'jquery', 'masonry', 'imagesloaded' ),
173
- COBLOCKS_VERSION,
174
- true
175
- );
176
- }
177
-
178
- // Carousel block.
179
- if ( has_block( 'coblocks/gallery-carousel', $header . $footer ) ) {
180
- wp_enqueue_script(
181
- 'coblocks-flickity',
182
- $vendors_dir . '/flickity' . COBLOCKS_ASSET_SUFFIX . '.js',
183
- array( 'jquery' ),
184
- COBLOCKS_VERSION,
185
- true
186
- );
187
- }
188
- }
189
- add_action( 'wp_enqueue_scripts', __NAMESPACE__ . '\enqueue_coblocks_gallery_scripts' );
190
-
191
- /**
192
- * Load Blog Posts block.
193
- */
194
- function load_blog_posts_block() {
195
- $disable_block = (
196
- in_array( 'newspack-blocks/newspack-blocks.php', (array) get_option( 'active_plugins', array() ), true ) ||
197
- in_array( 'newspack-blocks/newspack-blocks.php', (array) get_site_option( 'active_sitewide_plugins', array() ), true )
198
- );
199
-
200
- /**
201
- * Can be used to disable the Blog Posts block.
202
- *
203
- * @since 0.15.1
204
- *
205
- * @param bool $disable_block True if Blog Posts block should be enabled, false otherwise.
206
- */
207
- if ( apply_filters( 'a8c_disable_blog_posts_block', $disable_block ) ) {
208
- return;
209
- }
210
-
211
- require_once __DIR__ . '/blog-posts-block/index.php';
212
- }
213
- add_action( 'plugins_loaded', __NAMESPACE__ . '\load_blog_posts_block' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/blocks/navigation-menu/edit.js DELETED
@@ -1,98 +0,0 @@
1
- /* eslint-disable wpcalypso/jsx-classname-namespace */
2
- /* eslint-disable import/no-extraneous-dependencies */
3
- /**
4
- * WordPress dependencies
5
- */
6
- import ServerSideRender from '@wordpress/server-side-render';
7
- import { Fragment } from '@wordpress/element';
8
- import { compose } from '@wordpress/compose';
9
- import { __ } from '@wordpress/i18n';
10
- import {
11
- AlignmentToolbar,
12
- BlockControls,
13
- ContrastChecker,
14
- FontSizePicker,
15
- InspectorControls,
16
- PanelColorSettings,
17
- withColors,
18
- withFontSizes,
19
- } from '@wordpress/block-editor';
20
- import { PanelBody } from '@wordpress/components';
21
- import { withSelect } from '@wordpress/data';
22
-
23
- /**
24
- * Internal dependencies
25
- */
26
-
27
- const NavigationMenuEdit = ( {
28
- attributes,
29
- backgroundColor,
30
- fontSize,
31
- setAttributes,
32
- setBackgroundColor,
33
- setFontSize,
34
- setTextColor,
35
- textColor,
36
- isPublished,
37
- } ) => {
38
- const { customFontSize, textAlign } = attributes;
39
-
40
- const actualFontSize = customFontSize || fontSize.size;
41
-
42
- return (
43
- <Fragment>
44
- <BlockControls>
45
- <AlignmentToolbar
46
- value={ textAlign }
47
- onChange={ nextAlign => {
48
- setAttributes( { textAlign: nextAlign } );
49
- } }
50
- />
51
- </BlockControls>
52
- <InspectorControls>
53
- <PanelBody className="blocks-font-size" title={ __( 'Text Settings' ) }>
54
- <FontSizePicker onChange={ setFontSize } value={ actualFontSize } />
55
- </PanelBody>
56
- <PanelColorSettings
57
- title={ __( 'Color Settings' ) }
58
- initialOpen={ false }
59
- colorSettings={ [
60
- {
61
- value: backgroundColor.color,
62
- onChange: setBackgroundColor,
63
- label: __( 'Background Color' ),
64
- },
65
- {
66
- value: textColor.color,
67
- onChange: setTextColor,
68
- label: __( 'Text Color' ),
69
- },
70
- ] }
71
- >
72
- <ContrastChecker
73
- { ...{
74
- textColor: textColor.color,
75
- backgroundColor: backgroundColor.color,
76
- } }
77
- fontSize={ actualFontSize }
78
- />
79
- </PanelColorSettings>
80
- </InspectorControls>
81
- <ServerSideRender
82
- isPublished={ isPublished }
83
- block="a8c/navigation-menu"
84
- attributes={ attributes }
85
- />
86
- </Fragment>
87
- );
88
- };
89
-
90
- export default compose( [
91
- withColors( 'backgroundColor', { textColor: 'color' } ),
92
- withFontSizes( 'fontSize' ),
93
- withSelect( select => {
94
- return {
95
- isPublished: select( 'core/editor' ).isCurrentPostPublished(),
96
- };
97
- } ),
98
- ] )( NavigationMenuEdit );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/blocks/navigation-menu/index.js DELETED
@@ -1,33 +0,0 @@
1
- /* eslint-disable import/no-extraneous-dependencies */
2
- /**
3
- * WordPress dependencies
4
- */
5
- import { registerBlockType } from '@wordpress/blocks';
6
- import { __ } from '@wordpress/i18n';
7
-
8
- /**
9
- * Internal dependencies
10
- */
11
- import edit from './edit';
12
- import './style.scss';
13
-
14
- const icon = (
15
- <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
16
- <path fill="none" d="M0 0h24v24H0V0z" />
17
- <path d="M12 7.27l4.28 10.43-3.47-1.53-.81-.36-.81.36-3.47 1.53L12 7.27M12 2L4.5 20.29l.71.71L12 18l6.79 3 .71-.71L12 2z" />
18
- </svg>
19
- );
20
-
21
- registerBlockType( 'a8c/navigation-menu', {
22
- title: __( 'Navigation Menu' ),
23
- description: __( 'Visual placeholder for site-wide navigation and menus.' ),
24
- icon,
25
- category: 'layout',
26
- supports: {
27
- align: [ 'wide', 'full', 'right', 'left' ],
28
- html: false,
29
- reusable: false,
30
- },
31
- edit,
32
- save: () => null,
33
- } );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/blocks/navigation-menu/index.php DELETED
@@ -1,125 +0,0 @@
1
- <?php
2
- /**
3
- * Render navigation menu block file.
4
- *
5
- * @package A8C\FSE
6
- */
7
-
8
- namespace A8C\FSE;
9
-
10
- /**
11
- * Render the navigation menu.
12
- *
13
- * @param array $attributes Block attributes.
14
- * @return string
15
- */
16
- function render_navigation_menu_block( $attributes ) {
17
- $styles = '';
18
-
19
- $container_class = 'menu-primary-container';
20
- $toggle_class = 'button';
21
- if ( isset( $attributes['className'] ) ) {
22
- $container_class .= ' ' . $attributes['className'];
23
- $toggle_class .= ' ' . $attributes['className'];
24
- }
25
-
26
- $align = ' alignwide';
27
- if ( isset( $attributes['align'] ) ) {
28
- $align = empty( $attributes['align'] ) ? '' : ' align' . $attributes['align'];
29
- }
30
- $class = $align;
31
-
32
- if ( isset( $attributes['textAlign'] ) ) {
33
- $class .= ' has-text-align-' . $attributes['textAlign'];
34
- } else {
35
- $class .= ' has-text-align-center';
36
- }
37
-
38
- if ( isset( $attributes['textColor'] ) ) {
39
- $class .= ' has-text-color';
40
- $class .= ' has-' . $attributes['textColor'] . '-color';
41
- } elseif ( isset( $attributes['customTextColor'] ) ) {
42
- $class .= ' has-text-color';
43
- $styles .= ' color: ' . $attributes['customTextColor'] . ';';
44
- }
45
-
46
- if ( isset( $attributes['backgroundColor'] ) ) {
47
- $class .= ' has-background';
48
- $class .= ' has-' . $attributes['backgroundColor'] . '-background-color';
49
- } elseif ( isset( $attributes['customBackgroundColor'] ) ) {
50
- $class .= ' has-background';
51
- $styles .= ' background-color: ' . $attributes['customBackgroundColor'] . ';';
52
- }
53
-
54
- if ( isset( $attributes['customFontSize'] ) ) {
55
- $styles .= ' font-size: ' . $attributes['customFontSize'] . 'px;';
56
- } elseif ( isset( $attributes['fontSize'] ) ) {
57
- $class .= ' has-' . $attributes['fontSize'] . '-font-size';
58
- } else {
59
- $class .= ' has-small-font-size';
60
- }
61
-
62
- $container_class .= $class;
63
- $toggle_class .= $class;
64
-
65
- $menu = wp_nav_menu(
66
- [
67
- 'echo' => false,
68
- 'fallback_cb' => 'get_fallback_navigation_menu',
69
- 'items_wrap' => '<ul id="%1$s" class="%2$s" aria-label="submenu">%3$s</ul>',
70
- 'menu_class' => 'main-menu footer-menu',
71
- 'theme_location' => 'menu-1',
72
- 'container' => '',
73
- ]
74
- );
75
-
76
- ob_start();
77
- // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped
78
- ?>
79
- <nav class="main-navigation wp-block-a8c-navigation-menu<?php echo esc_attr( $align ); ?>">
80
- <input type="checkbox" role="button" aria-haspopup="true" id="toggle" class="hide-visually">
81
- <label for="toggle" id="toggle-menu" class="<?php echo esc_attr( $toggle_class ); ?>" style="<?php echo esc_attr( $styles ); ?>">
82
- <?php esc_html_e( 'Menu', 'full-site-editing' ); ?>
83
- <span class="dropdown-icon open">+</span>
84
- <span class="dropdown-icon close">&times;</span>
85
- <span class="hide-visually expanded-text"><?php esc_html_e( 'expanded', 'full-site-editing' ); ?></span>
86
- <span class="hide-visually collapsed-text"><?php esc_html_e( 'collapsed', 'full-site-editing' ); ?></span>
87
- </label>
88
- <div class="<?php echo esc_attr( $container_class ); ?>" style="<?php echo esc_attr( $styles ); ?>">
89
- <?php echo $menu ? $menu : get_fallback_navigation_menu(); ?>
90
- </div>
91
- </nav>
92
- <!-- #site-navigation -->
93
- <?php
94
- // phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped
95
- return ob_get_clean();
96
- }
97
-
98
- /**
99
- * Render a list of all site pages as a fallback
100
- * for when a menu does not exist.
101
- *
102
- * @return string
103
- */
104
- function get_fallback_navigation_menu() {
105
- $menu = wp_page_menu(
106
- [
107
- 'after' => false,
108
- 'before' => false,
109
- 'container' => 'ul',
110
- 'echo' => false,
111
- 'menu_class' => 'main-menu footer-menu',
112
- 'sort_column' => 'menu_order, post_date',
113
- ]
114
- );
115
-
116
- /**
117
- * Filter the fallback page menu to use the same
118
- * CSS class structure as a regularly built menu
119
- * so we don't have to duplicate CSS selectors everywhere.
120
- */
121
- $original_classes = [ 'children', 'page_item_has_sub-menu' ];
122
- $replacement_classes = [ 'sub-menu', 'menu-item-has-children' ];
123
-
124
- return str_replace( $original_classes, $replacement_classes, $menu );
125
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/blocks/navigation-menu/style.scss DELETED
@@ -1,3 +0,0 @@
1
- .wp-block-a8c-navigation-menu.main-navigation {
2
- pointer-events: none;
3
- }
 
 
 
trunk/full-site-editing/blocks/post-content/edit.js DELETED
@@ -1,62 +0,0 @@
1
- /* eslint-disable wpcalypso/jsx-classname-namespace */
2
-
3
- /**
4
- * External dependencies
5
- */
6
- import classNames from 'classnames';
7
-
8
- /**
9
- * WordPress dependencies
10
- */
11
- import { compose, withState } from '@wordpress/compose';
12
- import { withSelect } from '@wordpress/data';
13
- import { PostTitle } from '@wordpress/editor';
14
- import { InnerBlocks } from '@wordpress/block-editor';
15
- import { Component, Fragment } from '@wordpress/element';
16
-
17
- class PostContentEdit extends Component {
18
- toggleEditing() {
19
- const { isEditing, setState } = this.props;
20
- setState( { isEditing: ! isEditing } );
21
- }
22
-
23
- onSelectPost( { id, type } ) {
24
- this.props.setState( {
25
- isEditing: false,
26
- selectedPostId: id,
27
- selectedPostType: type,
28
- } );
29
- }
30
-
31
- render() {
32
- const { attributes } = this.props;
33
- const { align } = attributes;
34
-
35
- return (
36
- <Fragment>
37
- <div
38
- className={ classNames( 'post-content-block', {
39
- [ `align${ align }` ]: align,
40
- } ) }
41
- >
42
- <PostTitle />
43
- <InnerBlocks templateLock={ false } />
44
- </div>
45
- </Fragment>
46
- );
47
- }
48
- }
49
-
50
- export default compose( [
51
- withState( {
52
- isEditing: false,
53
- selectedPostId: undefined,
54
- selectedPostType: undefined,
55
- } ),
56
- withSelect( ( select, { selectedPostId, selectedPostType } ) => {
57
- const { getEntityRecord } = select( 'core' );
58
- return {
59
- selectedPost: getEntityRecord( 'postType', selectedPostType, selectedPostId ),
60
- };
61
- } ),
62
- ] )( PostContentEdit );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/blocks/post-content/index.js DELETED
@@ -1,57 +0,0 @@
1
- /* eslint-disable import/no-extraneous-dependencies */
2
- /**
3
- * External dependencies
4
- */
5
- import { createHigherOrderComponent } from '@wordpress/compose';
6
- import { registerBlockType } from '@wordpress/blocks';
7
- import { __ } from '@wordpress/i18n';
8
- import { addFilter } from '@wordpress/hooks';
9
-
10
- /**
11
- * Internal dependencies
12
- */
13
- import edit from './edit';
14
- import save from './save';
15
- import './style.scss';
16
-
17
- registerBlockType( 'a8c/post-content', {
18
- title: __( 'Content' ),
19
- description: __( 'The page content.' ),
20
- icon: 'layout',
21
- category: 'layout',
22
- supports: {
23
- align: [ 'full' ],
24
- anchor: false,
25
- customClassName: false,
26
- html: false,
27
- inserter: false,
28
- multiple: false,
29
- reusable: false,
30
- },
31
- attributes: {
32
- align: {
33
- type: 'string',
34
- default: 'full',
35
- },
36
- },
37
- edit,
38
- save,
39
- } );
40
-
41
- const addContentSlotClassname = createHigherOrderComponent( BlockListBlock => {
42
- return props => {
43
- if ( props.name !== 'a8c/post-content' ) {
44
- return <BlockListBlock { ...props } />;
45
- }
46
-
47
- return <BlockListBlock { ...props } className={ 'post-content__block' } />;
48
- };
49
- }, 'addContentSlotClassname' );
50
-
51
- // Must be 9 or this breaks on Simple Sites
52
- addFilter(
53
- 'editor.BlockListBlock',
54
- 'full-site-editing/blocks/post-content',
55
- addContentSlotClassname,
56
- 9
57
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/blocks/post-content/index.php DELETED
@@ -1,39 +0,0 @@
1
- <?php
2
- /**
3
- * Render post content block file.
4
- *
5
- * @package A8C\FSE
6
- */
7
-
8
- namespace A8C\FSE;
9
-
10
- /**
11
- * Renders post content.
12
- *
13
- * @param array $attributes Block attributes.
14
- * @param string $content Block content.
15
- * @return string
16
- */
17
- function render_post_content_block( $attributes, $content ) {
18
- // Early return to avoid infinite loops in the REST API.
19
- if ( is_admin() || ( defined( 'REST_REQUEST' ) && REST_REQUEST ) ) {
20
- return $content;
21
- }
22
-
23
- $align = isset( $attributes['align'] ) ? ' align' . $attributes['align'] : '';
24
-
25
- ob_start();
26
- ?>
27
-
28
- <div class="post-content<?php echo esc_attr( $align ); ?>">
29
- <?php
30
- // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
31
- echo apply_filters( 'the_content', get_the_content() );
32
- ?>
33
- </div><!-- .post-content -->
34
-
35
- <?php
36
- $content = ob_get_clean();
37
-
38
- return $content;
39
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/blocks/post-content/save.js DELETED
@@ -1,6 +0,0 @@
1
- /**
2
- * External dependencies
3
- */
4
- import { InnerBlocks } from '@wordpress/block-editor';
5
-
6
- export default () => <InnerBlocks.Content />;
 
 
 
 
 
 
trunk/full-site-editing/blocks/post-content/style.scss DELETED
@@ -1,69 +0,0 @@
1
- .post-content-block__selector {
2
- width: 300px;
3
- a {
4
- font-family: sans-serif;
5
- font-size: 13px;
6
- padding-left: 8px;
7
- }
8
- }
9
-
10
- .post-content-block__preview {
11
- pointer-events: none;
12
- &::after {
13
- content: '';
14
- clear: both;
15
- display: table;
16
- }
17
- }
18
-
19
- .post-content-block .editor-post-title {
20
- display: none;
21
- }
22
-
23
- .show-post-title-before-content {
24
- .editor-post-title {
25
- display: none;
26
- }
27
-
28
- .post-content-block .editor-post-title {
29
- display: block;
30
- }
31
- }
32
-
33
- /**
34
- * Hide the content slot block UI
35
- *
36
- * @TODO: Remove this once Gutenberg gets support for hiding block UI.
37
- *
38
- * @see https://github.com/WordPress/gutenberg/issues/7469
39
- * @see https://github.com/WordPress/gutenberg/pull/18173
40
- */
41
- .block-editor-block-list__layout {
42
- .post-content__block {
43
- &.is-selected {
44
- .block-editor-block-contextual-toolbar {
45
- display: none;
46
- }
47
- }
48
-
49
- &.block-editor-block-list__block {
50
- // Need to get super specific to override the core css selectors:
51
- &,
52
- &.has-child-selected,
53
- &.is-navigate-mode,
54
- &.is-hovered {
55
- > .block-editor-block-list__block-edit {
56
- &::before {
57
- transition: none;
58
- border: none;
59
- outline: none;
60
- box-shadow: none;
61
- }
62
- > .block-editor-block-list__breadcrumb {
63
- display: none;
64
- }
65
- }
66
- }
67
- }
68
- }
69
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/blocks/site-credit/edit.js DELETED
@@ -1,75 +0,0 @@
1
- /* eslint-disable wpcalypso/jsx-classname-namespace */
2
- /* eslint-disable import/no-extraneous-dependencies */
3
- /* global fullSiteEditing */
4
- /**
5
- * External dependencies
6
- */
7
- import classNames from 'classnames';
8
-
9
- /**
10
- * WordPress dependencies
11
- */
12
- import { AlignmentToolbar, BlockControls } from '@wordpress/block-editor';
13
- import { SelectControl } from '@wordpress/components';
14
- import { compose } from '@wordpress/compose';
15
- import { Fragment } from '@wordpress/element';
16
- import { __ } from '@wordpress/i18n';
17
-
18
- /**
19
- * Internal dependencies
20
- */
21
- import { withSiteOptions } from '../../lib';
22
- import { RenderedCreditChoice } from './footer-credit-choices';
23
-
24
- const { footerCreditOptions, defaultCreditOption } = fullSiteEditing;
25
-
26
- function SiteCreditEdit( {
27
- attributes: { textAlign = 'center' },
28
- isSelected,
29
- setAttributes,
30
- footerCreditOption: { value: wpCredit, updateValue: updateCredit },
31
- siteTitleOption: { value: siteTitle },
32
- } ) {
33
- const footerCreditChoice = wpCredit || defaultCreditOption;
34
- return (
35
- <Fragment>
36
- <BlockControls>
37
- <AlignmentToolbar
38
- value={ textAlign }
39
- onChange={ nextAlign => {
40
- setAttributes( { textAlign: nextAlign } );
41
- } }
42
- />
43
- </BlockControls>
44
- <div
45
- className={ classNames( 'site-info', 'site-credit__block', {
46
- [ `has-text-align-${ textAlign }` ]: textAlign,
47
- } ) }
48
- >
49
- <span className="site-name">{ siteTitle }</span>
50
- <span className="comma">,</span>
51
- <span className="site-credit__selection">
52
- { isSelected ? (
53
- <SelectControl
54
- onChange={ updateCredit }
55
- value={ footerCreditChoice }
56
- options={ footerCreditOptions }
57
- />
58
- ) : (
59
- <RenderedCreditChoice choice={ footerCreditChoice } />
60
- ) }
61
- </span>
62
- </div>
63
- </Fragment>
64
- );
65
- }
66
-
67
- export default compose( [
68
- withSiteOptions( {
69
- siteTitleOption: { optionName: 'title', defaultValue: __( 'Site title loading…' ) },
70
- footerCreditOption: {
71
- optionName: 'footer_credit',
72
- defaultValue: __( 'Footer credit loading…' ),
73
- },
74
- } ),
75
- ] )( SiteCreditEdit );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/blocks/site-credit/footer-credit-choices.js DELETED
@@ -1,24 +0,0 @@
1
- /* eslint-disable import/no-extraneous-dependencies */
2
- /* eslint-disable wpcalypso/import-docblock */
3
- /* global fullSiteEditing */
4
- /**
5
- * WordPress dependencies
6
- */
7
- import { Icon } from '@wordpress/components';
8
-
9
- const { footerCreditOptions } = fullSiteEditing;
10
-
11
- export const RenderedCreditChoice = ( { choice } ) => {
12
- const selection = footerCreditOptions.find( ( { value } ) => value === choice );
13
- if ( ! selection ) {
14
- return null;
15
- }
16
-
17
- const { renderType, renderProps, label } = selection;
18
- // Allows label to be overriden by renderProps if needed.
19
- const props = { label, ...renderProps };
20
- if ( 'icon' === renderType ) {
21
- return <Icon { ...props } />;
22
- }
23
- return <span> { props.label } </span>;
24
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/blocks/site-credit/index.js DELETED
@@ -1,38 +0,0 @@
1
- /* eslint-disable import/no-extraneous-dependencies */
2
- /**
3
- * WordPress dependencies
4
- */
5
- import { registerBlockType } from '@wordpress/blocks';
6
- import { __ } from '@wordpress/i18n';
7
-
8
- /**
9
- * Internal dependencies
10
- */
11
- import edit from './edit';
12
- import './style.scss';
13
-
14
- registerBlockType( 'a8c/site-credit', {
15
- title: __( 'WordPress.com Credit' ),
16
- description: __( "This block tells the world that you're using WordPress.com." ),
17
- icon: 'wordpress-alt',
18
- category: 'layout',
19
- supports: {
20
- align: [ 'wide', 'full' ],
21
- html: false,
22
- multiple: false,
23
- reusable: false,
24
- removal: false,
25
- },
26
- attributes: {
27
- align: {
28
- type: 'string',
29
- default: 'wide',
30
- },
31
- textAlign: {
32
- type: 'string',
33
- default: 'center',
34
- },
35
- },
36
- edit,
37
- save: () => null,
38
- } );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/blocks/site-credit/index.php DELETED
@@ -1,205 +0,0 @@
1
- <?php
2
- /**
3
- * Site credit backend functions.
4
- *
5
- * @package A8C\FSE
6
- */
7
-
8
- namespace A8C\FSE;
9
-
10
- /**
11
- * Renders the site credit block.
12
- *
13
- * @param array $attributes An associative array of block attributes.
14
- * @return string
15
- */
16
- function render_site_credit_block( $attributes ) {
17
- $class = get_credit_block_classes( $attributes );
18
-
19
- ob_start();
20
- // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped
21
-
22
- echo '<div class="' . esc_attr( $class ) . '">';
23
- if ( ! empty( get_bloginfo( 'name' ) ) ) {
24
- ?>
25
- <a class="site-name" href="<?php echo esc_url( home_url( '/' ) ); ?>" rel="home"><?php bloginfo( 'name' ); ?></a><span class="comma">,</span>
26
- <?php
27
- }
28
- echo get_credit_element();
29
- ?>
30
- </div>
31
- <?php
32
-
33
- // phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped
34
- return ob_get_clean();
35
- }
36
-
37
- /**
38
- * Gets the class names to wrap around the rendered credit block.
39
- *
40
- * For example, adds the 'alignfull' class if the block is set to align full.
41
- *
42
- * @param array $attributes An associative array of block attributes.
43
- * @return string The string of classes to add to the block.
44
- */
45
- function get_credit_block_classes( $attributes ) {
46
- $class = 'site-info';
47
- // Add text Alignment classes.
48
- if ( isset( $attributes['textAlign'] ) ) {
49
- $class .= ' has-text-align-' . $attributes['textAlign'];
50
- } else {
51
- $class .= ' has-text-align-center';
52
- }
53
-
54
- // Add Block Alignment classes.
55
- if ( isset( $attributes['align'] ) ) {
56
- $class .= ' align' . $attributes['align'];
57
- } else {
58
- $class .= ' alignwide';
59
- }
60
- return $class;
61
- }
62
-
63
- /**
64
- * Returns the credit element based on the user's settings.
65
- *
66
- * For example, this could be the WordPress icon or an attribution string.
67
- * It links the attribution to a filterable link.
68
- */
69
- function get_credit_element() {
70
- $credit_option = get_credit_information();
71
-
72
- if ( ! isset( $credit_option ) || ! is_array( $credit_option ) ) {
73
- return;
74
- }
75
- /**
76
- * Filter the link which gives credit to whoever runs the site.
77
- *
78
- * Defaults to wordpress.org.
79
- *
80
- * @param string The URL to filter.
81
- */
82
- $credit_link = esc_url( apply_filters( 'a8c_fse_get_footer_credit_link', 'https://wordpress.org/' ) );
83
-
84
- // Icon renderer.
85
- if ( 'icon' === $credit_option['renderType'] && isset( $credit_option['renderProps'] ) && isset( $credit_option['renderProps']['icon'] ) ) {
86
- $icon_class = 'dashicons dashicons-' . $credit_option['renderProps']['icon'];
87
- $element = '<a class="' . $icon_class . '" href="' . esc_url( $credit_link ) . '"></a>';
88
- } else {
89
- // Support custom label other than the default text to show the user in the Select element.
90
- if ( isset( $credit_option['renderProps'] ) && isset( $credit_option['renderProps']['label'] ) ) {
91
- $text = $credit_option['renderProps']['label'];
92
- } else {
93
- $text = $credit_option['label'];
94
- }
95
- $element = '<a href="' . $credit_link . '" class="imprint">' . $text . '</a>.';
96
- }
97
-
98
- return footercredit_rel_nofollow_link( $element );
99
- }
100
-
101
- /**
102
- * Adds `rel="nofollow"` to the footer credit link.
103
- *
104
- * @param string $link Link `<a>` tag.
105
- * @return string Link `<a>` tag.
106
- */
107
- function footercredit_rel_nofollow_link( $link ) {
108
- return wp_unslash( wp_rel_nofollow( wp_slash( $link ) ) );
109
- }
110
-
111
- /**
112
- * Note: this definition is mainly for use in the JS code for the block editor.
113
- * Most settings will still work
114
- *
115
- * @typedef CreditOption
116
- * @type {Object}
117
- * @property {string} label The text to show the user as an option.
118
- * @property {string} value The shorthand value to identify the option.
119
- * @property {string} [renderType] The type of render to use. Defaults to 'text',
120
- * which renders the label inside a <span/>. You
121
- * can also use 'icon' to render an icon from
122
- * @wordpress/components.
123
- * @property {Object} [renderProps] The props to pass into the renderer. For example,
124
- * for an icon, you could specify { icon: 'WordPress', color: 'gray' }
125
- * which get passed into <Icon /> as props in order to
126
- * render a gray WordPress icon. You can also specify
127
- * { label } here in order to override the text you show
128
- * to users as an option for text types.
129
- */
130
-
131
- /**
132
- * Gets the options to show the user in the WordPress credit block.
133
- *
134
- * Note: These values are added to the fullSiteEditing global for access in JS.
135
- *
136
- * @return Array<CreditOption> The credit options to show the user.
137
- */
138
- function get_footer_credit_options() {
139
- /**
140
- * Filter the Footer Credit options from which the user can choose.
141
- *
142
- * Defaults to a WordPress icon and a WordPress.org shout out.
143
- *
144
- * @param Array<CreditOption> The array of options to show the user.
145
- */
146
- return apply_filters(
147
- 'a8c_fse_update_footer_credit_options',
148
- [
149
- [
150
- 'label' => __( 'Proudly powered by WordPress' ),
151
- 'value' => 'default',
152
- 'renderType' => 'text',
153
- ],
154
- [
155
- 'label' => __( 'WordPress Icon' ),
156
- 'value' => 'svg',
157
- 'renderType' => 'icon',
158
- 'renderProps' => [
159
- 'icon' => 'wordpress',
160
- 'color' => 'gray',
161
- ],
162
- ],
163
- ]
164
- );
165
- }
166
-
167
- /**
168
- * Gets the default footer credit selection.
169
- *
170
- * Note: this should match the `value` of one the credit options specified in
171
- * get_footer_credit_options.
172
- *
173
- * @return string The default footer credit option.
174
- */
175
- function get_default_footer_credit_option() {
176
- /**
177
- * Filter the default footer credit option. Can be used to override the
178
- * value if the user has not yet chosen a footer credit option.
179
- *
180
- * @param string Default option value.
181
- */
182
- return apply_filters( 'a8c_fse_default_footer_credit_option', 'default' );
183
- }
184
-
185
- /**
186
- * Gets the credit information associated with the selected footer credit option.
187
- *
188
- * If no credit information is found, null is returned.
189
- *
190
- * @return [CreditOption] The info associated with the currently selected option.
191
- */
192
- function get_credit_information() {
193
- $credit_option = get_option( 'footercredit' );
194
- if ( false === $credit_option ) {
195
- $credit_option = get_default_footer_credit_option();
196
- }
197
-
198
- $credit_options = get_footer_credit_options();
199
- foreach ( $credit_options as $option ) {
200
- if ( $credit_option === $option['value'] ) {
201
- return $option;
202
- }
203
- }
204
- return null;
205
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/blocks/site-credit/style.scss DELETED
@@ -1,37 +0,0 @@
1
- .site-credit__block {
2
- display: flex;
3
- flex-direction: row;
4
- align-items: center;
5
- // @TODO: Pull these styles from the theme.
6
- font-size: 14px;
7
- color: gray;
8
-
9
- // Justify all elements based on text alignment.
10
- &.has-text-align-center {
11
- justify-content: center;
12
- }
13
- &.has-text-align-left {
14
- justify-content: flex-start;
15
- }
16
- &.has-text-align-right {
17
- justify-content: flex-end;
18
- }
19
-
20
- .site-name {
21
- font-weight: bold;
22
- }
23
-
24
- .site-credit__selection {
25
- margin-left: 5px;
26
-
27
- // Also align items vertically center in the selection area.
28
- display: flex;
29
- flex-direction: row;
30
- align-items: center;
31
-
32
- .components-base-control .components-base-control__field {
33
- // Reset extra margin added by @wordpress/components in the select field.
34
- margin-bottom: 0;
35
- }
36
- }
37
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/blocks/site-description/edit.js DELETED
@@ -1,140 +0,0 @@
1
- /* eslint-disable wpcalypso/jsx-classname-namespace */
2
- /* eslint-disable import/no-extraneous-dependencies */
3
- /**
4
- * External dependencies
5
- */
6
- import classNames from 'classnames';
7
- import { noop } from 'lodash';
8
-
9
- /**
10
- * WordPress dependencies
11
- */
12
- import {
13
- AlignmentToolbar,
14
- BlockControls,
15
- ContrastChecker,
16
- FontSizePicker,
17
- InspectorControls,
18
- PanelColorSettings,
19
- RichText,
20
- withColors,
21
- withFontSizes,
22
- } from '@wordpress/block-editor';
23
- import { compose } from '@wordpress/compose';
24
- import { withSelect, withDispatch } from '@wordpress/data';
25
- import { Fragment } from '@wordpress/element';
26
- import { __ } from '@wordpress/i18n';
27
- import { PanelBody } from '@wordpress/components';
28
-
29
- /**
30
- * Internal dependencies
31
- */
32
- import { withSiteOptions } from '../../lib';
33
-
34
- function SiteDescriptionEdit( {
35
- attributes,
36
- backgroundColor,
37
- className,
38
- fontSize,
39
- insertDefaultBlock,
40
- setAttributes,
41
- setBackgroundColor,
42
- setFontSize,
43
- setTextColor,
44
- siteDescription,
45
- textColor,
46
- } ) {
47
- const { customFontSize, textAlign } = attributes;
48
-
49
- const actualFontSize = customFontSize || fontSize.size;
50
-
51
- const { value, updateValue } = siteDescription;
52
-
53
- return (
54
- <Fragment>
55
- <BlockControls>
56
- <AlignmentToolbar
57
- value={ textAlign }
58
- onChange={ nextAlign => {
59
- setAttributes( { textAlign: nextAlign } );
60
- } }
61
- />
62
- </BlockControls>
63
- <InspectorControls>
64
- <PanelBody className="blocks-font-size" title={ __( 'Text Settings' ) }>
65
- <FontSizePicker onChange={ setFontSize } value={ actualFontSize } />
66
- </PanelBody>
67
- <PanelColorSettings
68
- title={ __( 'Color Settings' ) }
69
- initialOpen={ false }
70
- colorSettings={ [
71
- {
72
- value: backgroundColor.color,
73
- onChange: setBackgroundColor,
74
- label: __( 'Background Color' ),
75
- },
76
- {
77
- value: textColor.color,
78
- onChange: setTextColor,
79
- label: __( 'Text Color' ),
80
- },
81
- ] }
82
- >
83
- <ContrastChecker
84
- { ...{
85
- textColor: textColor.color,
86
- backgroundColor: backgroundColor.color,
87
- } }
88
- fontSize={ actualFontSize }
89
- />
90
- </PanelColorSettings>
91
- </InspectorControls>
92
- <RichText
93
- allowedFormats={ [] }
94
- aria-label={ __( 'Site Description' ) }
95
- className={ classNames( 'site-description', className, {
96
- 'has-text-color': textColor.color,
97
- 'has-background': backgroundColor.color,
98
- [ `has-text-align-${ textAlign }` ]: textAlign,
99
- [ backgroundColor.class ]: backgroundColor.class,
100
- [ textColor.class ]: textColor.class,
101
- [ fontSize.class ]: ! customFontSize && fontSize.class,
102
- } ) }
103
- identifier="content"
104
- onChange={ updateValue }
105
- onReplace={ insertDefaultBlock }
106
- onSplit={ noop }
107
- placeholder={ __( 'Add a Site Description' ) }
108
- style={ {
109
- backgroundColor: backgroundColor.color,
110
- color: textColor.color,
111
- fontSize: actualFontSize ? actualFontSize + 'px' : undefined,
112
- } }
113
- tagName="p"
114
- value={ value }
115
- />
116
- </Fragment>
117
- );
118
- }
119
-
120
- export default compose( [
121
- withColors( 'backgroundColor', { textColor: 'color' } ),
122
- withFontSizes( 'fontSize' ),
123
- withSelect( ( select, { clientId } ) => {
124
- const { getBlockIndex, getBlockRootClientId, getTemplateLock } = select( 'core/block-editor' );
125
- const rootClientId = getBlockRootClientId( clientId );
126
-
127
- return {
128
- blockIndex: getBlockIndex( clientId, rootClientId ),
129
- isLocked: !! getTemplateLock( rootClientId ),
130
- rootClientId,
131
- };
132
- } ),
133
- withDispatch( ( dispatch, { blockIndex, rootClientId } ) => ( {
134
- insertDefaultBlock: () =>
135
- dispatch( 'core/block-editor' ).insertDefaultBlock( {}, rootClientId, blockIndex + 1 ),
136
- } ) ),
137
- withSiteOptions( {
138
- siteDescription: { optionName: 'description', defaultValue: __( 'Site description loading…' ) },
139
- } ),
140
- ] )( SiteDescriptionEdit );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/blocks/site-description/index.js DELETED
@@ -1,61 +0,0 @@
1
- /* eslint-disable import/no-extraneous-dependencies */
2
- /**
3
- * WordPress dependencies
4
- */
5
- import { registerBlockType } from '@wordpress/blocks';
6
- import { __ } from '@wordpress/i18n';
7
-
8
- /**
9
- * Internal dependencies
10
- */
11
- import edit from './edit';
12
- import './style.scss';
13
-
14
- registerBlockType( 'a8c/site-description', {
15
- title: __( 'Site Description' ),
16
- description: __( 'Site description, also known as the tagline.' ),
17
- icon: (
18
- <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24">
19
- <path fill="none" d="M0 0h24v24H0z" />
20
- <path d="M4 9h16v2H4V9zm0 4h10v2H4v-2z" />
21
- </svg>
22
- ),
23
- category: 'layout',
24
- supports: {
25
- align: [ 'wide', 'full' ],
26
- html: false,
27
- multiple: false,
28
- reusable: false,
29
- },
30
- attributes: {
31
- align: {
32
- type: 'string',
33
- default: 'wide',
34
- },
35
- textAlign: {
36
- type: 'string',
37
- default: 'center',
38
- },
39
- textColor: {
40
- type: 'string',
41
- },
42
- customTextColor: {
43
- type: 'string',
44
- },
45
- backgroundColor: {
46
- type: 'string',
47
- },
48
- customBackgroundColor: {
49
- type: 'string',
50
- },
51
- fontSize: {
52
- type: 'string',
53
- default: 'small',
54
- },
55
- customFontSize: {
56
- type: 'number',
57
- },
58
- },
59
- edit,
60
- save: () => null,
61
- } );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/blocks/site-description/index.php DELETED
@@ -1,68 +0,0 @@
1
- <?php
2
- /**
3
- * Render site description file.
4
- *
5
- * @package A8C\FSE
6
- */
7
-
8
- namespace A8C\FSE;
9
-
10
- /**
11
- * Renders the site description (tagline) block.
12
- *
13
- * @param array $attributes Block attributes.
14
- * @return string
15
- */
16
- function render_site_description_block( $attributes ) {
17
- ob_start();
18
-
19
- $styles = '';
20
-
21
- $class = 'site-description wp-block-a8c-site-description';
22
- if ( isset( $attributes['className'] ) ) {
23
- $class .= ' ' . $attributes['className'];
24
- }
25
-
26
- $align = ' alignwide';
27
- if ( isset( $attributes['align'] ) ) {
28
- $align = empty( $attributes['align'] ) ? '' : ' align' . $attributes['align'];
29
- }
30
- $class .= $align;
31
-
32
- if ( isset( $attributes['textAlign'] ) ) {
33
- $class .= ' has-text-align-' . $attributes['textAlign'];
34
- } else {
35
- $class .= ' has-text-align-center';
36
- }
37
-
38
- if ( isset( $attributes['textColor'] ) ) {
39
- $class .= ' has-text-color';
40
- $class .= ' has-' . $attributes['textColor'] . '-color';
41
- } elseif ( isset( $attributes['customTextColor'] ) ) {
42
- $class .= ' has-text-color';
43
- $styles .= ' color: ' . $attributes['customTextColor'] . ';';
44
- }
45
-
46
- if ( isset( $attributes['backgroundColor'] ) ) {
47
- $class .= ' has-background';
48
- $class .= ' has-' . $attributes['backgroundColor'] . '-background-color';
49
- } elseif ( isset( $attributes['customBackgroundColor'] ) ) {
50
- $class .= ' has-background';
51
- $styles .= ' background-color: ' . $attributes['customBackgroundColor'] . ';';
52
- }
53
-
54
- if ( isset( $attributes['fontSize'] ) ) {
55
- $class .= ' has-' . $attributes['fontSize'] . '-font-size';
56
- } elseif ( isset( $attributes['customFontSize'] ) ) {
57
- $styles .= ' font-size: ' . $attributes['customFontSize'] . 'px;';
58
- } else {
59
- $class .= ' has-small-font-size';
60
- }
61
-
62
- ?>
63
- <p class="<?php echo esc_attr( $class ); ?>" style="<?php echo esc_attr( $styles ); ?>">
64
- <?php bloginfo( 'description' ); ?>
65
- </p>
66
- <?php
67
- return ob_get_clean();
68
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/blocks/site-description/style.scss DELETED
@@ -1,12 +0,0 @@
1
- @import '../../sass/mixins';
2
-
3
- .block-editor {
4
- .wp-block-a8c-site-description:focus {
5
- box-shadow: none;
6
- background-color: transparent;
7
- }
8
-
9
- .wp-block.is-selected .wp-block-a8c-site-description {
10
- @include hide-input-placeholder;
11
- }
12
- }
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/blocks/site-title/edit.js DELETED
@@ -1,121 +0,0 @@
1
- /* eslint-disable wpcalypso/jsx-classname-namespace */
2
- /* eslint-disable import/no-extraneous-dependencies */
3
- /**
4
- * External dependencies
5
- */
6
- import classNames from 'classnames';
7
- import { noop } from 'lodash';
8
-
9
- /**
10
- * WordPress dependencies
11
- */
12
- import { __ } from '@wordpress/i18n';
13
- import {
14
- AlignmentToolbar,
15
- BlockControls,
16
- FontSizePicker,
17
- InspectorControls,
18
- PanelColorSettings,
19
- RichText,
20
- withColors,
21
- withFontSizes,
22
- } from '@wordpress/block-editor';
23
- import { withSelect, withDispatch } from '@wordpress/data';
24
- import { compose } from '@wordpress/compose';
25
- import { Fragment } from '@wordpress/element';
26
- import { PanelBody } from '@wordpress/components';
27
-
28
- /**
29
- * Internal dependencies
30
- */
31
- import { withSiteOptions } from '../../lib';
32
-
33
- function SiteTitleEdit( {
34
- attributes,
35
- className,
36
- fontSize,
37
- insertDefaultBlock,
38
- setAttributes,
39
- setFontSize,
40
- setTextColor,
41
- siteTitle,
42
- textColor,
43
- } ) {
44
- const { customFontSize, textAlign } = attributes;
45
-
46
- const actualFontSize = customFontSize || fontSize.size;
47
-
48
- const { value, updateValue } = siteTitle;
49
-
50
- return (
51
- <Fragment>
52
- <BlockControls>
53
- <AlignmentToolbar
54
- value={ textAlign }
55
- onChange={ nextAlign => {
56
- setAttributes( { textAlign: nextAlign } );
57
- } }
58
- />
59
- </BlockControls>
60
- <InspectorControls>
61
- <PanelBody className="blocks-font-size" title={ __( 'Text Settings' ) }>
62
- <FontSizePicker onChange={ setFontSize } value={ actualFontSize } />
63
- </PanelBody>
64
- <PanelColorSettings
65
- title={ __( 'Color Settings' ) }
66
- initialOpen={ false }
67
- colorSettings={ [
68
- {
69
- value: textColor.color,
70
- onChange: setTextColor,
71
- label: __( 'Text Color' ),
72
- },
73
- ] }
74
- />
75
- </InspectorControls>
76
- <RichText
77
- allowedFormats={ [] }
78
- aria-label={ __( 'Site Title' ) }
79
- className={ classNames( 'site-title', className, {
80
- 'has-text-color': textColor.color,
81
- [ `has-text-align-${ textAlign }` ]: textAlign,
82
- [ textColor.class ]: textColor.class,
83
- [ fontSize.class ]: ! customFontSize && fontSize.class,
84
- } ) }
85
- identifier="content"
86
- onChange={ updateValue }
87
- onReplace={ insertDefaultBlock }
88
- onSplit={ noop }
89
- placeholder={ __( 'Add a Site Title' ) }
90
- style={ {
91
- color: textColor.color,
92
- fontSize: actualFontSize ? actualFontSize + 'px' : undefined,
93
- } }
94
- tagName="h1"
95
- value={ value }
96
- />
97
- </Fragment>
98
- );
99
- }
100
-
101
- export default compose( [
102
- withColors( { textColor: 'color' } ),
103
- withFontSizes( 'fontSize' ),
104
- withSelect( ( select, { clientId } ) => {
105
- const { getBlockIndex, getBlockRootClientId, getTemplateLock } = select( 'core/block-editor' );
106
- const rootClientId = getBlockRootClientId( clientId );
107
-
108
- return {
109
- blockIndex: getBlockIndex( clientId, rootClientId ),
110
- isLocked: !! getTemplateLock( rootClientId ),
111
- rootClientId,
112
- };
113
- } ),
114
- withDispatch( ( dispatch, { blockIndex, rootClientId } ) => ( {
115
- insertDefaultBlock: () =>
116
- dispatch( 'core/block-editor' ).insertDefaultBlock( {}, rootClientId, blockIndex + 1 ),
117
- } ) ),
118
- withSiteOptions( {
119
- siteTitle: { optionName: 'title', defaultValue: __( 'Site title loading…' ) },
120
- } ),
121
- ] )( SiteTitleEdit );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/blocks/site-title/index.js DELETED
@@ -1,50 +0,0 @@
1
- /* eslint-disable import/no-extraneous-dependencies */
2
- /**
3
- * WordPress dependencies
4
- */
5
- import { registerBlockType } from '@wordpress/blocks';
6
- import { __ } from '@wordpress/i18n';
7
-
8
- /**
9
- * Internal dependencies
10
- */
11
- import edit from './edit';
12
- import './style.scss';
13
-
14
- registerBlockType( 'a8c/site-title', {
15
- title: __( 'Site Title' ),
16
- description: __( 'Your site title.' ),
17
- icon: 'layout',
18
- category: 'layout',
19
- supports: {
20
- align: [ 'wide', 'full' ],
21
- html: false,
22
- multiple: false,
23
- reusable: false,
24
- },
25
- attributes: {
26
- align: {
27
- type: 'string',
28
- default: 'wide',
29
- },
30
- textAlign: {
31
- type: 'string',
32
- default: 'center',
33
- },
34
- textColor: {
35
- type: 'string',
36
- },
37
- customTextColor: {
38
- type: 'string',
39
- },
40
- fontSize: {
41
- type: 'string',
42
- default: 'normal',
43
- },
44
- customFontSize: {
45
- type: 'number',
46
- },
47
- },
48
- edit,
49
- save: () => null,
50
- } );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/blocks/site-title/index.php DELETED
@@ -1,62 +0,0 @@
1
- <?php
2
- /**
3
- * Render site title block.
4
- *
5
- * @package A8C\FSE
6
- */
7
-
8
- namespace A8C\FSE;
9
-
10
- /**
11
- * Renders the site title and allows for editing in the full site editor.
12
- *
13
- * @param array $attributes Block attributes.
14
- * @return string
15
- */
16
- function render_site_title_block( $attributes ) {
17
- ob_start();
18
-
19
- $styles = '';
20
-
21
- $class = 'site-title wp-block-a8c-site-title';
22
- if ( isset( $attributes['className'] ) ) {
23
- $class .= ' ' . $attributes['className'];
24
- }
25
-
26
- $align = ' alignwide';
27
- if ( isset( $attributes['align'] ) ) {
28
- $align = empty( $attributes['align'] ) ? '' : ' align' . $attributes['align'];
29
- }
30
- $class .= $align;
31
-
32
- if ( isset( $attributes['textAlign'] ) ) {
33
- $class .= ' has-text-align-' . $attributes['textAlign'];
34
- } else {
35
- $class .= ' has-text-align-center';
36
- }
37
-
38
- if ( isset( $attributes['textColor'] ) ) {
39
- $class .= ' has-text-color';
40
- $class .= ' has-' . $attributes['textColor'] . '-color';
41
- } elseif ( isset( $attributes['customTextColor'] ) ) {
42
- $class .= ' has-text-color';
43
- $styles .= ' color: ' . $attributes['customTextColor'] . ';';
44
- }
45
-
46
- if ( isset( $attributes['fontSize'] ) ) {
47
- $class .= ' has-' . $attributes['fontSize'] . '-font-size';
48
- } elseif ( isset( $attributes['customFontSize'] ) ) {
49
- $styles .= ' font-size: ' . $attributes['customFontSize'] . 'px;';
50
- } else {
51
- $class .= ' has-normal-font-size';
52
- }
53
-
54
- ?>
55
- <h1 class="<?php echo esc_attr( $class ); ?>" style="<?php echo esc_attr( $styles ); ?>">
56
- <a href="<?php echo esc_url( home_url( '/' ) ); ?>"><?php bloginfo( 'name' ); ?></a>
57
- </h1>
58
- <!-- a8c:site-title -->
59
- <?php
60
- return ob_get_clean();
61
- }
62
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/blocks/site-title/style.scss DELETED
@@ -1,12 +0,0 @@
1
- @import '../../sass/mixins';
2
-
3
- .block-editor {
4
- .wp-block-a8c-site-title:focus {
5
- box-shadow: none;
6
- background-color: transparent;
7
- }
8
-
9
- .wp-block.is-selected .wp-block-a8c-site-title {
10
- @include hide-input-placeholder;
11
- }
12
- }
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/blocks/template/edit.js DELETED
@@ -1,201 +0,0 @@
1
- /* eslint-disable import/no-extraneous-dependencies */
2
- /* eslint-disable wpcalypso/jsx-classname-namespace */
3
- /* global fullSiteEditing */
4
- /**
5
- * External dependencies
6
- */
7
- import classNames from 'classnames';
8
- import { get, noop } from 'lodash';
9
-
10
- /**
11
- * WordPress dependencies
12
- */
13
- import { parse, createBlock } from '@wordpress/blocks';
14
- import { BlockEdit } from '@wordpress/block-editor';
15
- import { Button, Placeholder, Spinner, Disabled } from '@wordpress/components';
16
- import { compose, withState } from '@wordpress/compose';
17
- import { withDispatch, withSelect } from '@wordpress/data';
18
- import { Fragment, useEffect, useState, createRef } from '@wordpress/element';
19
- import { __, sprintf } from '@wordpress/i18n';
20
- import { addQueryArgs } from '@wordpress/url';
21
-
22
- /**
23
- * Internal dependencies
24
- */
25
- import './style.scss';
26
-
27
- const TemplateEdit = compose(
28
- withState( { templateClientId: null } ),
29
- withSelect( ( select, { attributes, templateClientId } ) => {
30
- const { getEntityRecord } = select( 'core' );
31
- const { getCurrentPostId, isEditedPostDirty } = select( 'core/editor' );
32
- const { getBlock, getSelectedBlock } = select( 'core/block-editor' );
33
- const { isEditorSidebarOpened } = select( 'core/edit-post' );
34
- const { templateId } = attributes;
35
- const currentPostId = getCurrentPostId();
36
- const template = templateId && getEntityRecord( 'postType', 'wp_template_part', templateId );
37
- const editTemplateUrl = addQueryArgs( fullSiteEditing.editTemplateBaseUrl, {
38
- post: templateId,
39
- fse_parent_post: currentPostId,
40
- } );
41
- const selectedBlock = getSelectedBlock();
42
-
43
- return {
44
- currentPostId,
45
- editTemplateUrl,
46
- template,
47
- templateBlock: getBlock( templateClientId ),
48
- templateTitle: get( template, [ 'title', 'rendered' ], '' ),
49
- isDirty: isEditedPostDirty(),
50
- isEditorSidebarOpened: !! isEditorSidebarOpened(),
51
- isAnyTemplateBlockSelected: selectedBlock && 'a8c/template' === selectedBlock.name,
52
- };
53
- } ),
54
- withDispatch( ( dispatch, ownProps ) => {
55
- const { receiveBlocks } = dispatch( 'core/block-editor' );
56
- const { openGeneralSidebar } = dispatch( 'core/edit-post' );
57
- const { template, templateClientId, setState } = ownProps;
58
- return {
59
- savePost: dispatch( 'core/editor' ).savePost,
60
- receiveTemplateBlocks: () => {
61
- if ( ! template || templateClientId ) {
62
- return;
63
- }
64
-
65
- const templateBlocks = parse( get( template, [ 'content', 'raw' ], '' ) );
66
- const templateBlock = createBlock( 'core/group', {}, templateBlocks );
67
-
68
- receiveBlocks( [ templateBlock ] );
69
- setState( { templateClientId: templateBlock.clientId } );
70
- },
71
- openGeneralSidebar,
72
- };
73
- } )
74
- )(
75
- ( {
76
- attributes,
77
- editTemplateUrl,
78
- receiveTemplateBlocks,
79
- template,
80
- templateBlock,
81
- templateTitle,
82
- isDirty,
83
- savePost,
84
- isEditorSidebarOpened,
85
- openGeneralSidebar,
86
- isAnyTemplateBlockSelected,
87
- } ) => {
88
- if ( ! template ) {
89
- return (
90
- <Placeholder>
91
- <Spinner />
92
- </Placeholder>
93
- );
94
- }
95
- const navButton = createRef();
96
- const [ navigateToTemplate, setNavigateToTemplate ] = useState( false );
97
- useEffect( () => {
98
- if ( navigateToTemplate && ! isDirty ) {
99
- // Since we cancelled the click event to save the post
100
- // we trigger it again here. We do this instead of setting
101
- // window.location.href because in WordPress.com, the navigation
102
- // scheme is different and not available to us here.
103
- navButton.current.click();
104
- }
105
- receiveTemplateBlocks();
106
- } );
107
-
108
- useEffect( () => {
109
- // Since the Block Sidebar (`edit-post/block`) is not available for the Template block,
110
- // if the sidebar is open, we force toggle to the Document Sidebar, and hide the Block button.
111
- const blockSidebarButton = document.querySelector(
112
- '.edit-post-sidebar__panel-tabs ul li:last-child'
113
- );
114
- if ( isEditorSidebarOpened && blockSidebarButton ) {
115
- if ( isAnyTemplateBlockSelected ) {
116
- openGeneralSidebar( 'edit-post/document' );
117
- blockSidebarButton.classList.add( 'hidden' );
118
- return;
119
- }
120
- blockSidebarButton.classList.remove( 'hidden' );
121
- }
122
- }, [ isAnyTemplateBlockSelected, isEditorSidebarOpened, openGeneralSidebar ] );
123
-
124
- const { align, className } = attributes;
125
-
126
- const save = event => {
127
- event.stopPropagation();
128
- setNavigateToTemplate( true );
129
- if ( ! isDirty ) {
130
- return;
131
- }
132
- /**
133
- * This must be after setNavigateToTemplate so that local navigation
134
- * (without wpcom overrides) still works correctly.
135
- */
136
- event.preventDefault();
137
- savePost();
138
- };
139
-
140
- /**
141
- * IMPORTANT: Be careful about changes to the overlay button. There is code in
142
- * iframe-bridge-server.js (setupEditTemplateLinks) which looks for two
143
- * elements matching '.template__block-container .template-block__overlay a'.
144
- * This code updates the href of the button to match the calypso URL (which is
145
- * sent through the iFrame port) since editTemplateUrl here will be the wpadmin URL.
146
- *
147
- * If you make changes to the button, navigation to the template editor MAY BREAK.
148
- *
149
- * For example, if the button does not exist in the DOM as the editor is loaded,
150
- * the links may not be updated in time, or an interval will continuously try to
151
- * find them (which is bad for performance).
152
- *
153
- * This has already broken several times, so be careful!
154
- */
155
-
156
- return (
157
- <div
158
- className={ classNames( 'template-block', {
159
- [ `align${ align }` ]: align,
160
- 'is-navigating-to-template': navigateToTemplate,
161
- } ) }
162
- >
163
- { templateBlock && (
164
- <Fragment>
165
- <Disabled>
166
- <div className={ className }>
167
- <BlockEdit
168
- attributes={ templateBlock.attributes }
169
- block={ templateBlock }
170
- clientId={ templateBlock.clientId }
171
- isSelected={ false }
172
- name={ templateBlock.name }
173
- setAttributes={ noop }
174
- />
175
- </div>
176
- </Disabled>
177
- <Placeholder className="template-block__overlay" onClick={ save }>
178
- { navigateToTemplate && (
179
- <div className="template-block__loading">
180
- <Spinner /> { sprintf( __( 'Loading editor for: %s' ), templateTitle ) }
181
- </div>
182
- ) }
183
- <Button
184
- className={ navigateToTemplate ? 'hidden' : null }
185
- href={ editTemplateUrl }
186
- onClick={ save }
187
- isDefault
188
- isLarge
189
- ref={ navButton }
190
- >
191
- { sprintf( __( 'Edit %s' ), templateTitle ) }
192
- </Button>
193
- </Placeholder>
194
- </Fragment>
195
- ) }
196
- </div>
197
- );
198
- }
199
- );
200
-
201
- export default TemplateEdit;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/blocks/template/index.js DELETED
@@ -1,60 +0,0 @@
1
- /* global fullSiteEditing */
2
- /**
3
- * WordPress dependencies
4
- */
5
- import { registerBlockType } from '@wordpress/blocks';
6
- import { __ } from '@wordpress/i18n';
7
- import { createHigherOrderComponent } from '@wordpress/compose';
8
- import { addFilter } from '@wordpress/hooks';
9
-
10
- /**
11
- * Internal dependencies
12
- */
13
- import edit from './edit';
14
- import './style.scss';
15
- import './site-logo';
16
-
17
- if ( 'wp_template_part' !== fullSiteEditing.editorPostType ) {
18
- registerBlockType( 'a8c/template', {
19
- title: __( 'Template Part' ),
20
- __experimentalDisplayName: 'label',
21
- description: __( 'Display a Template Part.' ),
22
- icon: 'layout',
23
- category: 'layout',
24
- attributes: {
25
- templateId: { type: 'number' },
26
- className: { type: 'string' },
27
- label: { type: 'string' },
28
- },
29
- supports: {
30
- anchor: false,
31
- customClassName: false,
32
- html: false,
33
- inserter: false,
34
- reusable: false,
35
- },
36
- edit,
37
- save: () => null,
38
- getEditWrapperProps() {
39
- return { 'data-align': 'full' };
40
- },
41
- } );
42
- }
43
-
44
- const addFSETemplateClassname = createHigherOrderComponent( BlockListBlock => {
45
- return props => {
46
- if ( props.name !== 'a8c/template' ) {
47
- return <BlockListBlock { ...props } />;
48
- }
49
-
50
- return <BlockListBlock { ...props } className="template__block-container" />;
51
- };
52
- }, 'addFSETemplateClassname' );
53
-
54
- // Must be 9 or this breaks on Simple Sites
55
- addFilter(
56
- 'editor.BlockListBlock',
57
- 'full-site-editing/blocks/template',
58
- addFSETemplateClassname,
59
- 9
60
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/blocks/template/index.php DELETED
@@ -1,41 +0,0 @@
1
- <?php
2
- /**
3
- * Render template block file.
4
- *
5
- * @package A8C\FSE
6
- */
7
-
8
- namespace A8C\FSE;
9
-
10
- /**
11
- * Renders template.
12
- *
13
- * @param array $attributes Block attributes.
14
- * @return string
15
- */
16
- function render_template_block( $attributes ) {
17
- if ( ! isset( $attributes['templateId'] ) || ! is_int( $attributes['templateId'] ) ) {
18
- return;
19
- }
20
-
21
- $template = get_post( $attributes['templateId'] );
22
-
23
- $align = isset( $attributes['align'] ) ? ' align' . $attributes['align'] : '';
24
-
25
- setup_postdata( $template );
26
- ob_start();
27
- ?>
28
-
29
- <div class="template<?php echo esc_attr( $align ); ?>">
30
- <?php
31
- // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
32
- echo apply_filters( 'the_content', get_the_content() );
33
- ?>
34
- </div><!-- .template -->
35
-
36
- <?php
37
- $content = ob_get_clean();
38
- wp_reset_postdata();
39
-
40
- return $content;
41
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/blocks/template/site-logo.js DELETED
@@ -1,18 +0,0 @@
1
- /* eslint-disable wpcalypso/import-docblock */
2
- /**
3
- * WordPress dependencies
4
- */
5
- import { createHigherOrderComponent } from '@wordpress/compose';
6
- import { addFilter } from '@wordpress/hooks';
7
-
8
- const addFSESiteLogoClassname = createHigherOrderComponent( BlockListBlock => {
9
- return props => {
10
- if ( props.attributes.className !== 'fse-site-logo' ) {
11
- return <BlockListBlock { ...props } />;
12
- }
13
-
14
- return <BlockListBlock { ...props } className="template__site-logo" />;
15
- };
16
- }, 'addFSESiteLogoClassname' );
17
-
18
- addFilter( 'editor.BlockListBlock', 'full-site-editing/blocks/template', addFSESiteLogoClassname );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/blocks/template/style.scss DELETED
@@ -1,102 +0,0 @@
1
- .template-block {
2
- min-height: 200px;
3
- // Prevent blur bleeding
4
- overflow: hidden;
5
- position: relative;
6
- }
7
-
8
- // Override some very specific theme styles.
9
- .post-type-page .editor-styles-wrapper .template-block .fse-template-part {
10
- padding: 0;
11
- }
12
-
13
- .template__block-container {
14
- &.is-hovered {
15
- cursor: pointer;
16
- }
17
-
18
- &.is-hovered,
19
- &.is-selected,
20
- .is-navigating-to-template {
21
- .components-disabled {
22
- filter: blur( 2px );
23
- transition: filter 0.2s linear;
24
- }
25
- .template-block__overlay {
26
- opacity: 1;
27
- transition: opacity 0.2s linear;
28
- .components-button {
29
- opacity: 1;
30
- transition: opacity 0.2s linear;
31
- }
32
- }
33
- }
34
-
35
- .components-disabled {
36
- filter: blur( 0 );
37
- transition: filter 0.2s linear 0s;
38
- }
39
-
40
- // Hide the block toolbar and border
41
- .block-editor-block-contextual-toolbar,
42
- .block-editor-block-list__block-mobile-toolbar,
43
- .block-editor-block-list__insertion-point,
44
- .block-editor-block-list__breadcrumb,
45
- .block-editor-block-list__block-edit::before {
46
- display: none;
47
- }
48
- }
49
-
50
- .template-block__overlay {
51
- background: rgba( #ffffff, 0.8 );
52
- border: 0 solid rgba( #7b86a2, 0.3 ); // Gutenberg $dark-opacity-light-600
53
- bottom: 0;
54
- left: 0;
55
- margin: 0;
56
- opacity: 0;
57
- padding: 0;
58
- position: absolute;
59
- right: 0;
60
- transition: opacity 0.2s linear 0s;
61
- top: 0;
62
- z-index: 2;
63
-
64
- .is-selected & {
65
- border-color: rgba( #425863, 0.4 ); // Gutenberg $dark-opacity-light-800
66
- }
67
-
68
- .editor-block-list__block:first-child & {
69
- border-bottom-width: 1px;
70
- }
71
- .editor-block-list__block:last-child & {
72
- border-top-width: 1px;
73
- }
74
-
75
- @media only screen and ( min-width: 768px ) {
76
- border-width: 1px;
77
- }
78
-
79
- .components-button {
80
- opacity: 0;
81
- transition: opacity 0.2s linear 0s;
82
- &.hidden {
83
- display: none;
84
- }
85
- }
86
- }
87
-
88
- .template-block__loading {
89
- display: flex;
90
- align-items: center;
91
- color: #191e23;
92
- }
93
-
94
- // Hide the site logo description and buttons when not editing the Template
95
- .block-editor-page:not( .post-type-wp_template_part ) {
96
- .fse-site-logo {
97
- .components-placeholder__fieldset,
98
- .components-placeholder__instructions {
99
- display: none;
100
- }
101
- }
102
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/class-full-site-editing.php DELETED
@@ -1,628 +0,0 @@
1
- <?php
2
- /**
3
- * Full site editing file.
4
- *
5
- * @package A8C\FSE
6
- */
7
-
8
- namespace A8C\FSE;
9
-
10
- /**
11
- * Class Full_Site_Editing
12
- */
13
- class Full_Site_Editing {
14
- /**
15
- * Class instance.
16
- *
17
- * @var \A8C\FSE\Full_Site_Editing
18
- */
19
- private static $instance = null;
20
-
21
- /**
22
- * Custom post types.
23
- *
24
- * @var array
25
- */
26
- private $template_post_types = [ 'wp_template_part' ];
27
-
28
- /**
29
- * Current theme slug.
30
- *
31
- * @var string
32
- */
33
- private $theme_slug = '';
34
-
35
- /**
36
- * Instance of WP_Template_Inserter class.
37
- *
38
- * @var WP_Template_Inserter
39
- */
40
- public $wp_template_inserter;
41
-
42
- /**
43
- * Full_Site_Editing constructor.
44
- */
45
- private function __construct() {
46
- add_action( 'init', [ $this, 'register_blocks' ], 100 );
47
- add_action( 'init', [ $this, 'register_template_post_types' ] );
48
- add_action( 'enqueue_block_editor_assets', [ $this, 'enqueue_script_and_style' ], 100 );
49
- add_action( 'the_post', [ $this, 'merge_template_and_post' ] );
50
- add_filter( 'wp_insert_post_data', [ $this, 'remove_template_components' ], 10, 2 );
51
- add_filter( 'admin_body_class', [ $this, 'toggle_editor_post_title_visibility' ] );
52
- add_filter( 'block_editor_settings', [ $this, 'set_block_template' ] );
53
- add_filter( 'body_class', array( $this, 'add_fse_body_class' ) );
54
-
55
- add_filter( 'post_row_actions', [ $this, 'remove_trash_row_action_for_template_post_types' ], 10, 2 );
56
- add_filter( 'bulk_actions-edit-wp_template', [ $this, 'remove_trash_bulk_action_for_template_post_type' ] );
57
- add_action( 'wp_trash_post', [ $this, 'restrict_template_deletion' ] );
58
- add_action( 'before_delete_post', [ $this, 'restrict_template_deletion' ] );
59
- add_filter( 'wp_template_type_row_actions', [ $this, 'remove_delete_row_action_for_template_taxonomy' ], 10, 2 );
60
- add_filter( 'bulk_actions-edit-wp_template_type', [ $this, 'remove_delete_bulk_action_for_template_taxonomy' ] );
61
- add_action( 'pre_delete_term', [ $this, 'restrict_template_taxonomy_deletion' ], 10, 2 );
62
- add_action( 'transition_post_status', [ $this, 'restrict_template_drafting' ], 10, 3 );
63
- add_action( 'admin_menu', [ $this, 'remove_wp_admin_menu_items' ] );
64
-
65
- $this->theme_slug = normalize_theme_slug( get_stylesheet() );
66
- $this->wp_template_inserter = new WP_Template_Inserter( $this->theme_slug );
67
- }
68
-
69
- /**
70
- * Creates instance.
71
- *
72
- * @return \A8C\FSE\Full_Site_Editing
73
- */
74
- public static function get_instance() {
75
- if ( null === self::$instance ) {
76
- self::$instance = new self();
77
- }
78
-
79
- return self::$instance;
80
- }
81
-
82
- /**
83
- * Inserts template data for the theme we are currently switching to.
84
- *
85
- * This insertion will only happen if theme supports FSE.
86
- * It is hooked into after_switch_theme action.
87
- */
88
- public function insert_default_data() {
89
- // Bail if current theme doesn't support FSE.
90
- if ( ! is_theme_supported() ) {
91
- return;
92
- }
93
-
94
- $this->wp_template_inserter->insert_default_template_data();
95
- $this->wp_template_inserter->insert_default_pages();
96
- }
97
-
98
- /**
99
- * Register post types.
100
- */
101
- public function register_template_post_types() {
102
- $this->wp_template_inserter->register_template_post_types();
103
- }
104
-
105
- /**
106
- * Auth callback.
107
- *
108
- * @return mixed
109
- */
110
- public function meta_template_id_auth_callback() {
111
- return current_user_can( 'edit_theme_options' );
112
- }
113
-
114
- /**
115
- * Enqueue assets.
116
- */
117
- public function enqueue_script_and_style() {
118
- $asset_file = include plugin_dir_path( __FILE__ ) . 'dist/full-site-editing.asset.php';
119
- $script_dependencies = $asset_file['dependencies'];
120
- wp_enqueue_script(
121
- 'a8c-full-site-editing-script',
122
- plugins_url( 'dist/full-site-editing.js', __FILE__ ),
123
- is_array( $script_dependencies ) ? $script_dependencies : array(),
124
- filemtime( plugin_dir_path( __FILE__ ) . 'dist/full-site-editing.js' ),
125
- true
126
- );
127
-
128
- wp_localize_script(
129
- 'a8c-full-site-editing-script',
130
- 'fullSiteEditing',
131
- array(
132
- 'editorPostType' => get_current_screen()->post_type,
133
- 'closeButtonLabel' => $this->get_close_button_label(),
134
- 'closeButtonUrl' => esc_url( $this->get_close_button_url() ),
135
- 'editTemplateBaseUrl' => esc_url( $this->get_edit_template_base_url() ),
136
- )
137
- );
138
-
139
- $style_file = is_rtl()
140
- ? 'full-site-editing.rtl.css'
141
- : 'full-site-editing.css';
142
- wp_enqueue_style(
143
- 'a8c-full-site-editing-style',
144
- plugins_url( 'dist/' . $style_file, __FILE__ ),
145
- 'wp-edit-post',
146
- filemtime( plugin_dir_path( __FILE__ ) . 'dist/' . $style_file )
147
- );
148
- }
149
-
150
- /**
151
- * Register blocks.
152
- */
153
- public function register_blocks() {
154
- register_block_type(
155
- 'a8c/navigation-menu',
156
- array(
157
- 'attributes' => [
158
- 'className' => [
159
- 'type' => 'string',
160
- 'default' => '',
161
- ],
162
- 'align' => [
163
- 'type' => 'string',
164
- 'default' => 'wide',
165
- ],
166
- 'textAlign' => [
167
- 'type' => 'string',
168
- 'default' => 'center',
169
- ],
170
- 'textColor' => [
171
- 'type' => 'string',
172
- ],
173
- 'customTextColor' => [
174
- 'type' => 'string',
175
- ],
176
- 'backgroundColor' => [
177
- 'type' => 'string',
178
- ],
179
- 'customBackgroundColor' => [
180
- 'type' => 'string',
181
- ],
182
- 'fontSize' => [
183
- 'type' => 'string',
184
- 'default' => 'normal',
185
- ],
186
- 'customFontSize' => [
187
- 'type' => 'number',
188
- ],
189
- ],
190
- 'render_callback' => __NAMESPACE__ . '\render_navigation_menu_block',
191
- )
192
- );
193
-
194
- register_block_type(
195
- 'a8c/post-content',
196
- array(
197
- 'render_callback' => __NAMESPACE__ . '\render_post_content_block',
198
- )
199
- );
200
-
201
- register_block_type(
202
- 'a8c/site-description',
203
- array(
204
- 'render_callback' => __NAMESPACE__ . '\render_site_description_block',
205
- )
206
- );
207
-
208
- register_block_type(
209
- 'a8c/template',
210
- array(
211
- 'render_callback' => __NAMESPACE__ . '\render_template_block',
212
- )
213
- );
214
-
215
- register_block_type(
216
- 'a8c/site-title',
217
- array(
218
- 'render_callback' => __NAMESPACE__ . '\render_site_title_block',
219
- )
220
- );
221
- }
222
-
223
- /**
224
- * Returns the parent post ID if sent as query param when editing a Template from a
225
- * Post/Page or a Template.
226
- *
227
- * @return null|string The parent post ID, or null if not set.
228
- */
229
- public function get_parent_post_id() {
230
- // phpcs:disable WordPress.Security.NonceVerification
231
- if ( ! isset( $_GET['fse_parent_post'] ) ) {
232
- return null;
233
- }
234
-
235
- $parent_post_id = absint( $_GET['fse_parent_post'] );
236
- // phpcs:enable WordPress.Security.NonceVerification
237
-
238
- if ( empty( $parent_post_id ) ) {
239
- return null;
240
- }
241
-
242
- return $parent_post_id;
243
- }
244
-
245
- /**
246
- * Returns the label for the Gutenberg close button.
247
- *
248
- * When we edit a Template from a Post/Page or a Template, we want to replace the close
249
- * icon with a "Back to" button, to clarify that it will take us back to the previous editing
250
- * view, and not the Template CPT list.
251
- *
252
- * @return null|string Override label string if it should be inserted, or null otherwise.
253
- */
254
- public function get_close_button_label() {
255
- $parent_post_id = $this->get_parent_post_id();
256
-
257
- if ( ! $parent_post_id ) {
258
- return null;
259
- }
260
-
261
- $parent_post_type = get_post_type( $parent_post_id );
262
-
263
- // See https://github.com/Automattic/wp-calypso/issues/38075#issuecomment-559900054.
264
- if ( 'page' === $parent_post_type ) {
265
- return __( 'Page Layout' );
266
- }
267
-
268
- $parent_post_type_object = get_post_type_object( $parent_post_type );
269
-
270
- /* translators: %s: "Back to Post", "Back to Page", "Back to Template", etc. */
271
- return sprintf( __( 'Back to %s', 'full-site-editing' ), $parent_post_type_object->labels->singular_name );
272
- }
273
-
274
- /**
275
- * Returns the URL for the Gutenberg close button.
276
- *
277
- * In some cases we want to override the default value which would take us to post listing
278
- * for a given post type. For example, when navigating back from Header, we want to show the
279
- * parent page editing view, and not the Template CPT list.
280
- *
281
- * @return null|string Override URL string if it should be inserted, or null otherwise.
282
- */
283
- public function get_close_button_url() {
284
- $parent_post_id = $this->get_parent_post_id();
285
-
286
- if ( ! $parent_post_id ) {
287
- return null;
288
- }
289
-
290
- $close_button_url = get_edit_post_link( $parent_post_id );
291
-
292
- /**
293
- * Filter the Gutenberg's close button URL when editing Template CPTs.
294
- *
295
- * @since 0.1
296
- *
297
- * @param string Current close button URL.
298
- */
299
- return apply_filters( 'a8c_fse_close_button_link', $close_button_url );
300
- }
301
-
302
- /**
303
- * Returns the base URL for the Edit Template button. The URL does not contain neither
304
- * the post ID nor the template ID. Those query arguments should be provided by
305
- * the Template on the Block.
306
- *
307
- * @return string edit link without post ID
308
- */
309
- public function get_edit_template_base_url() {
310
- $edit_post_link = remove_query_arg( 'post', get_edit_post_link( 0, 'edit' ) );
311
-
312
- /**
313
- * Filter the Gutenberg's edit template button base URL
314
- * when editing pages or posts.
315
- *
316
- * @since 0.2
317
- *
318
- * @param string Current edit button URL.
319
- */
320
- return apply_filters( 'a8c_fse_edit_template_base_url', $edit_post_link );
321
- }
322
-
323
- /** This will merge the post content with the post template, modifiying the $post parameter.
324
- *
325
- * @param \WP_Post $post Post instance.
326
- */
327
- public function merge_template_and_post( $post ) {
328
- // Bail if not a REST API Request and not in the editor.
329
- if ( ! $this->should_merge_template_and_post( $post ) ) {
330
- return;
331
- }
332
-
333
- $template = new WP_Template();
334
- $template_content = $template->get_page_template_content();
335
-
336
- // Bail if the template has no post content block.
337
- if ( ! has_block( 'a8c/post-content', $template_content ) ) {
338
- return;
339
- }
340
-
341
- $post->post_content = preg_replace( '@(<!-- wp:a8c/post-content)(.*?)(/-->)@', "$1$2-->$post->post_content<!-- /wp:a8c/post-content -->", $template_content );
342
- }
343
-
344
- /**
345
- * Detects if we are in a context where the template and post should be merged.
346
- *
347
- * Conditions:
348
- * 1. Current theme supports it
349
- * 2. AND in a REST API request (either flavour)
350
- * 3. OR on a block editor screen (inlined requests using `rest_preload_api_request` )
351
- * 4. AND editing a post_type that supports full site editing
352
- *
353
- * @param \WP_Post $post object for the check.
354
- * @return bool
355
- */
356
- private function should_merge_template_and_post( $post ) {
357
- $is_rest_api_wpcom = ( defined( 'REST_API_REQUEST' ) && REST_API_REQUEST );
358
- $is_rest_api_core = ( defined( 'REST_REQUEST' ) && REST_REQUEST );
359
- $is_block_editor_screen = ( function_exists( 'get_current_screen' ) && get_current_screen() && get_current_screen()->is_block_editor() );
360
-
361
- if ( ! ( $is_block_editor_screen || $is_rest_api_core || $is_rest_api_wpcom ) ) {
362
- return false;
363
- }
364
- return $this->is_full_site_page( $post );
365
- }
366
-
367
- /**
368
- * This will extract the inner blocks of the post content and
369
- * serialize them back to HTML for saving.
370
- *
371
- * @param array $data An array of slashed post data.
372
- * @param array $postarr An array of sanitized, but otherwise unmodified post data.
373
- * @return array
374
- */
375
- public function remove_template_components( $data, $postarr ) {
376
- // Bail if the post type is one of the template post types.
377
- if ( in_array( $postarr['post_type'], $this->template_post_types, true ) ) {
378
- return $data;
379
- }
380
-
381
- $post_content = wp_unslash( $data['post_content'] );
382
-
383
- // Bail if post content has no blocks.
384
- if ( ! has_blocks( $post_content ) ) {
385
- return $data;
386
- }
387
-
388
- $post_content_blocks = parse_blocks( $post_content );
389
- $post_content_key = array_search( 'a8c/post-content', array_column( $post_content_blocks, 'blockName' ), true );
390
-
391
- // Bail if no post content block found.
392
- if ( ! $post_content_key ) {
393
- return $data;
394
- }
395
-
396
- $data['post_content'] = wp_slash( serialize_blocks( $post_content_blocks[ $post_content_key ]['innerBlocks'] ) );
397
- return $data;
398
- }
399
-
400
- /**
401
- * Return an extra class that will be assigned to the body element if a full site page is being edited.
402
- *
403
- * That class hides the default post title of the editor and displays a new post title rendered by the post content
404
- * block in order to have it just before the content of the post.
405
- *
406
- * @param string $classes Space-separated list of CSS classes.
407
- * @return string
408
- */
409
- public function toggle_editor_post_title_visibility( $classes ) {
410
- if ( get_current_screen()->is_block_editor() && $this->is_full_site_page() ) {
411
- $classes .= ' show-post-title-before-content ';
412
- }
413
- return $classes;
414
- }
415
-
416
- /**
417
- * Sets the block template to be loaded by the editor when creating a new full site page.
418
- *
419
- * @param array $editor_settings Default editor settings.
420
- * @return array Editor settings with the updated template setting.
421
- */
422
- public function set_block_template( $editor_settings ) {
423
- if ( $this->is_full_site_page() ) {
424
- $fse_template = new WP_Template();
425
- $template_blocks = $fse_template->get_template_blocks();
426
-
427
- $template = array();
428
- foreach ( $template_blocks as $block ) {
429
- $template[] = $this->fse_map_block_to_editor_template_setting( $block );
430
- }
431
- $editor_settings['template'] = $template;
432
- $editor_settings['templateLock'] = 'all';
433
- }
434
- return $editor_settings;
435
- }
436
-
437
- /**
438
- * Determine if the current edited post is a full site page.
439
- * So far we only support static pages.
440
- *
441
- * @param object $post optional post object, if not passed in then current post is checked.
442
- * @return boolean
443
- */
444
- public function is_full_site_page( $post = null ) {
445
- $post_type = get_post_type( $post );
446
- return 'page' === $post_type || ( 'revision' === $post_type && 'page' === get_post_type( $post->post_parent ) );
447
- }
448
-
449
- /**
450
- * Determines whether given post belongs to FSE template CPTs.
451
- *
452
- * @param WP_Post $post Check if this post belongs to templates.
453
- *
454
- * @return boolean
455
- */
456
- public function is_template_post_type( $post ) {
457
- return in_array( $post->post_type, $this->template_post_types, true );
458
- }
459
-
460
- /**
461
- * Add fse-enabled class to body so we can target css only if plugin enabled.
462
- *
463
- * @param array $classes classes to be applied to body.
464
- * @return array classes to be applied to body.
465
- */
466
- public function add_fse_body_class( $classes ) {
467
- $classes[] = 'fse-enabled';
468
- return $classes;
469
- }
470
-
471
- /**
472
- * Returns an array with the expected format of the block template setting syntax.
473
- *
474
- * @see https://github.com/WordPress/gutenberg/blob/1414cf0ad1ec3d0f3e86a40815513c15938bb522/docs/designers-developers/developers/block-api/block-templates.md
475
- *
476
- * @param array $block Block to convert.
477
- * @return array
478
- */
479
- private function fse_map_block_to_editor_template_setting( $block ) {
480
- $block_name = $block['blockName'];
481
- $attrs = $block['attrs'];
482
- $inner_blocks = $block['innerBlocks'];
483
-
484
- $inner_blocks_template = array();
485
- foreach ( $inner_blocks as $inner_block ) {
486
- $inner_blocks[] = fse_map_block_to_editor_template_setting( $inner_block );
487
- }
488
- return array( $block_name, $attrs, $inner_blocks_template );
489
- }
490
-
491
- /**
492
- * Removes the Trash action from the quick actions on the Templates list
493
- *
494
- * @param array $actions Array of row action links.
495
- * @param WP_Post $post The post object.
496
- * @return array
497
- */
498
- public function remove_trash_row_action_for_template_post_types( $actions, $post ) {
499
- if ( $this->is_template_post_type( $post ) ) {
500
- unset( $actions['trash'] );
501
- }
502
- return $actions;
503
- }
504
-
505
- /**
506
- * Removes the Trash bulk action from the Template List page.
507
- *
508
- * @param array $bulk_actions Array of bulk actions.
509
- * @return array;
510
- */
511
- public function remove_trash_bulk_action_for_template_post_type( $bulk_actions ) {
512
- unset( $bulk_actions['trash'] );
513
- return $bulk_actions;
514
- }
515
-
516
- /**
517
- * Prevents posts for the template post types to be deleted.
518
- *
519
- * @param integer $post_id The post id.
520
- */
521
- public function restrict_template_deletion( $post_id ) {
522
- if ( $this->is_template_post_type( get_post( $post_id ) ) ) {
523
- wp_die( esc_html__( 'Templates cannot be deleted.' ) );
524
- }
525
- }
526
-
527
- // phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
528
- /**
529
- * Prevents draftinig of template post types.
530
- *
531
- * @param string $new_status New post status.
532
- * @param string $old_status Old post status.
533
- * @param object $post Post object for which the status change is attempted.
534
- */
535
- public function restrict_template_drafting( $new_status, $old_status, $post ) {
536
- if ( 'draft' === $new_status && $this->is_template_post_type( $post ) ) {
537
- wp_die( esc_html__( 'Templates cannot be moved to drafts.' ) );
538
- }
539
- }
540
- // phpcs:enable Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
541
-
542
- /**
543
- * Removes the Delete action from the quick actions for the template taxonomy.
544
- *
545
- * @param array $actions Array of row action links.
546
- * @param WP_Term $term The Term object.
547
- * @return array
548
- */
549
- public function remove_delete_row_action_for_template_taxonomy( $actions, $term ) {
550
- if ( 'wp_template_part_type' === $term->taxonomy ) {
551
- unset( $actions['delete'] );
552
- }
553
- return $actions;
554
- }
555
-
556
- /**
557
- * Removes the Delete bulk action from the Template Taxonomy list.
558
- *
559
- * @param array $bulk_actions Array of bulk actions.
560
- * @return array
561
- */
562
- public function remove_delete_bulk_action_for_template_taxonomy( $bulk_actions ) {
563
- unset( $bulk_actions['delete'] );
564
- return $bulk_actions;
565
- }
566
-
567
- /**
568
- * Prevents template types to be deleted.
569
- *
570
- * @param integer $term The Term Id.
571
- * @param string $taxonomy Taxonomy name.
572
- */
573
- public function restrict_template_taxonomy_deletion( $term, $taxonomy ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
574
- if ( 'wp_template_part_type' === $taxonomy ) {
575
- wp_die( esc_html__( 'Template Types cannon be deleted.' ) );
576
- }
577
- }
578
-
579
- /**
580
- * Removes wp admin menu items we don't want like Customize and Widgets.
581
- */
582
- public function remove_wp_admin_menu_items() {
583
- global $submenu;
584
-
585
- // For safety.
586
- if ( ! \A8C\FSE\is_full_site_editing_active() ) {
587
- return;
588
- }
589
-
590
- // Remove widget submenu.
591
- remove_submenu_page( 'themes.php', 'widgets.php' );
592
-
593
- /*
594
- * This position is hardcoded in `wp-admin/menu.php` and we can't use `remove_submenu_page`
595
- * because the customize URL varies depending on the current screen.
596
- *
597
- * We also want to access the customizer through the URL, so we shouldn't deny URL access.
598
- */
599
- if ( isset( $submenu['themes.php'][6] ) ) {
600
- unset( $submenu['themes.php'][6] );
601
- }
602
- }
603
-
604
- /**
605
- * Registers the footer credit option for API use.
606
- */
607
- public function register_footer_credit_setting() {
608
- /**
609
- * Note: We do not want to create the option if it doesn't exist. This
610
- * way, the default option can theoretically change if the user switches
611
- * site types without changing an option in the list at all. As soon as
612
- * they make a change to the selection, however, it will be persisted.
613
- */
614
-
615
- // Registers the footercredit option for API use.
616
- register_setting(
617
- 'general',
618
- 'footercredit',
619
- [
620
- 'show_in_rest' => [
621
- 'name' => 'footer_credit',
622
- ],
623
- 'type' => 'string',
624
- 'description' => __( 'WordPress Footer Credit' ),
625
- ]
626
- );
627
- }
628
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/dist/full-site-editing.asset.php DELETED
@@ -1 +0,0 @@
1
- <?php return array('dependencies' => array('lodash', 'react-dom', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-dom-ready', 'wp-editor', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n', 'wp-plugins', 'wp-polyfill', 'wp-server-side-render', 'wp-url'), 'version' => 'd314406eee809bf46daf3796c393d1b0');
 
trunk/full-site-editing/dist/full-site-editing.css DELETED
@@ -1 +0,0 @@
1
- .wp-block-a8c-navigation-menu.main-navigation{pointer-events:none}.post-content-block__selector{width:300px}.post-content-block__selector a{font-family:sans-serif;font-size:13px;padding-left:8px}.post-content-block__preview{pointer-events:none}.post-content-block__preview:after{content:"";clear:both;display:table}.post-content-block .editor-post-title,.show-post-title-before-content .editor-post-title{display:none}.show-post-title-before-content .post-content-block .editor-post-title{display:block}.block-editor-block-list__layout .post-content__block.is-selected .block-editor-block-contextual-toolbar{display:none}.block-editor-block-list__layout .post-content__block.block-editor-block-list__block.has-child-selected>.block-editor-block-list__block-edit:before,.block-editor-block-list__layout .post-content__block.block-editor-block-list__block.is-hovered>.block-editor-block-list__block-edit:before,.block-editor-block-list__layout .post-content__block.block-editor-block-list__block.is-navigate-mode>.block-editor-block-list__block-edit:before,.block-editor-block-list__layout .post-content__block.block-editor-block-list__block>.block-editor-block-list__block-edit:before{transition:none;border:none;outline:none;box-shadow:none}.block-editor-block-list__layout .post-content__block.block-editor-block-list__block.has-child-selected>.block-editor-block-list__block-edit>.block-editor-block-list__breadcrumb,.block-editor-block-list__layout .post-content__block.block-editor-block-list__block.is-hovered>.block-editor-block-list__block-edit>.block-editor-block-list__breadcrumb,.block-editor-block-list__layout .post-content__block.block-editor-block-list__block.is-navigate-mode>.block-editor-block-list__block-edit>.block-editor-block-list__breadcrumb,.block-editor-block-list__layout .post-content__block.block-editor-block-list__block>.block-editor-block-list__block-edit>.block-editor-block-list__breadcrumb{display:none}.site-credit__block{display:flex;flex-direction:row;align-items:center;font-size:14px;color:grey}.site-credit__block.has-text-align-center{justify-content:center}.site-credit__block.has-text-align-left{justify-content:flex-start}.site-credit__block.has-text-align-right{justify-content:flex-end}.site-credit__block .site-name{font-weight:700}.site-credit__block .site-credit__selection{margin-left:5px;display:flex;flex-direction:row;align-items:center}.site-credit__block .site-credit__selection .components-base-control .components-base-control__field{margin-bottom:0}.block-editor .wp-block-a8c-site-description:focus{box-shadow:none;background-color:transparent}.block-editor .wp-block.is-selected .wp-block-a8c-site-description::-webkit-input-placeholder{color:transparent}.block-editor .wp-block.is-selected .wp-block-a8c-site-description:-moz-placeholder,.block-editor .wp-block.is-selected .wp-block-a8c-site-description::-moz-placeholder{color:transparent}.block-editor .wp-block.is-selected .wp-block-a8c-site-description:-ms-input-placeholder{color:transparent}.block-editor .wp-block-a8c-site-title:focus{box-shadow:none;background-color:transparent}.block-editor .wp-block.is-selected .wp-block-a8c-site-title::-webkit-input-placeholder{color:transparent}.block-editor .wp-block.is-selected .wp-block-a8c-site-title:-moz-placeholder,.block-editor .wp-block.is-selected .wp-block-a8c-site-title::-moz-placeholder{color:transparent}.block-editor .wp-block.is-selected .wp-block-a8c-site-title:-ms-input-placeholder{color:transparent}.template-block{min-height:200px;overflow:hidden;position:relative}.post-type-page .editor-styles-wrapper .template-block .fse-template-part{padding:0}.template__block-container.is-hovered{cursor:pointer}.template__block-container.is-hovered .components-disabled,.template__block-container .is-navigating-to-template .components-disabled,.template__block-container.is-selected .components-disabled{filter:blur(2px);transition:filter .2s linear}.template__block-container.is-hovered .template-block__overlay,.template__block-container.is-hovered .template-block__overlay .components-button,.template__block-container .is-navigating-to-template .template-block__overlay,.template__block-container .is-navigating-to-template .template-block__overlay .components-button,.template__block-container.is-selected .template-block__overlay,.template__block-container.is-selected .template-block__overlay .components-button{opacity:1;transition:opacity .2s linear}.template__block-container .components-disabled{filter:blur(0);transition:filter .2s linear 0s}.template__block-container .block-editor-block-contextual-toolbar,.template__block-container .block-editor-block-list__block-edit:before,.template__block-container .block-editor-block-list__block-mobile-toolbar,.template__block-container .block-editor-block-list__breadcrumb,.template__block-container .block-editor-block-list__insertion-point{display:none}.template-block__overlay{background:hsla(0,0%,100%,.8);border:0 solid rgba(123,134,162,.3);bottom:0;left:0;margin:0;opacity:0;padding:0;position:absolute;right:0;transition:opacity .2s linear 0s;top:0;z-index:2}.is-selected .template-block__overlay{border-color:rgba(66,88,99,.4)}.editor-block-list__block:first-child .template-block__overlay{border-bottom-width:1px}.editor-block-list__block:last-child .template-block__overlay{border-top-width:1px}@media only screen and (min-width:768px){.template-block__overlay{border-width:1px}}.template-block__overlay .components-button{opacity:0;transition:opacity .2s linear 0s}.template-block__overlay .components-button.hidden{display:none}.template-block__loading{display:flex;align-items:center;color:#191e23}.block-editor-page:not(.post-type-wp_template_part) .fse-site-logo .components-placeholder__fieldset,.block-editor-page:not(.post-type-wp_template_part) .fse-site-logo .components-placeholder__instructions,.close-button-override-thin,.post-type-page .edit-post-fullscreen-mode-close__toolbar,.post-type-post .edit-post-fullscreen-mode-close__toolbar,.post-type-wp_template_part .edit-post-fullscreen-mode-close__toolbar{display:none}.post-type-page .edit-post-fullscreen-mode-close__toolbar__override,.post-type-post .edit-post-fullscreen-mode-close__toolbar__override,.post-type-wp_template_part .edit-post-fullscreen-mode-close__toolbar__override{display:flex;align-items:center;padding:9px 10px;margin-left:-8px;border:none;border-right:1px solid #e2e4e7}.post-type-page .edit-post-fullscreen-mode-close__toolbar__override a,.post-type-page .edit-post-fullscreen-mode-close__toolbar__override a:active,.post-type-page .edit-post-fullscreen-mode-close__toolbar__override a:hover,.post-type-page .edit-post-fullscreen-mode-close__toolbar__override a:link,.post-type-page .edit-post-fullscreen-mode-close__toolbar__override a:visited,.post-type-post .edit-post-fullscreen-mode-close__toolbar__override a,.post-type-post .edit-post-fullscreen-mode-close__toolbar__override a:active,.post-type-post .edit-post-fullscreen-mode-close__toolbar__override a:hover,.post-type-post .edit-post-fullscreen-mode-close__toolbar__override a:link,.post-type-post .edit-post-fullscreen-mode-close__toolbar__override a:visited,.post-type-wp_template_part .edit-post-fullscreen-mode-close__toolbar__override a,.post-type-wp_template_part .edit-post-fullscreen-mode-close__toolbar__override a:active,.post-type-wp_template_part .edit-post-fullscreen-mode-close__toolbar__override a:hover,.post-type-wp_template_part .edit-post-fullscreen-mode-close__toolbar__override a:link,.post-type-wp_template_part .edit-post-fullscreen-mode-close__toolbar__override a:visited{text-decoration:none}.post-type-page .edit-post-fullscreen-mode-close__toolbar__override .close-button-override__label,.post-type-post .edit-post-fullscreen-mode-close__toolbar__override .close-button-override__label,.post-type-wp_template_part .edit-post-fullscreen-mode-close__toolbar__override .close-button-override__label{font-size:13px}.post-type-page .edit-post-fullscreen-mode-close__toolbar__override .dashicons-arrow-left-alt2,.post-type-post .edit-post-fullscreen-mode-close__toolbar__override .dashicons-arrow-left-alt2,.post-type-wp_template_part .edit-post-fullscreen-mode-close__toolbar__override .dashicons-arrow-left-alt2{margin-left:-7px}@media (max-width:599px){.post-type-page .edit-post-fullscreen-mode-close__toolbar__override,.post-type-post .edit-post-fullscreen-mode-close__toolbar__override,.post-type-wp_template_part .edit-post-fullscreen-mode-close__toolbar__override{margin-left:-2px}}@media (max-width:400px){.post-type-page .edit-post-fullscreen-mode-close__toolbar__override .close-button-override-wide,.post-type-post .edit-post-fullscreen-mode-close__toolbar__override .close-button-override-wide,.post-type-wp_template_part .edit-post-fullscreen-mode-close__toolbar__override .close-button-override-wide{display:none}.post-type-page .edit-post-fullscreen-mode-close__toolbar__override .close-button-override-thin,.post-type-post .edit-post-fullscreen-mode-close__toolbar__override .close-button-override-thin,.post-type-wp_template_part .edit-post-fullscreen-mode-close__toolbar__override .close-button-override-thin{display:flex}.post-type-page .edit-post-fullscreen-mode-close__toolbar__override .close-button-override__label,.post-type-post .edit-post-fullscreen-mode-close__toolbar__override .close-button-override__label,.post-type-wp_template_part .edit-post-fullscreen-mode-close__toolbar__override .close-button-override__label{display:none}}.post-type-wp_template_part .edit-post-post-status,.post-type-wp_template_part .editor-post-title,.post-type-wp_template_part .editor-post-trash{display:none}.post-type-wp_template_part .edit-post-visual-editor{margin-top:20px;padding-top:0}.post-type-wp_template_part .editor-post-switch-to-draft{display:none}@media (min-width:768px){.post-type-page .edit-post-editor-regions__content,.post-type-page .edit-post-layout__content,.post-type-wp_template_part .edit-post-editor-regions__content,.post-type-wp_template_part .edit-post-layout__content{background:#eee}.post-type-page .edit-post-editor-regions__content .edit-post-visual-editor,.post-type-page .edit-post-layout__content .edit-post-visual-editor,.post-type-wp_template_part .edit-post-editor-regions__content .edit-post-visual-editor,.post-type-wp_template_part .edit-post-layout__content .edit-post-visual-editor{box-shadow:0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.12),0 1px 5px 0 rgba(0,0,0,.2);flex:none;margin:36px 32px}}.post-type-page .block-editor-block-list__layout,.post-type-wp_template_part .block-editor-block-list__layout{padding-left:0;padding-right:0}.post-type-page .block-editor-block-list__block[data-align=full]>.block-editor-block-list__block-edit,.post-type-wp_template_part .block-editor-block-list__block[data-align=full]>.block-editor-block-list__block-edit{margin-right:0;margin-left:0}.post-type-page .block-editor-block-list__block[data-align=wide]>.block-editor-block-list__block-edit,.post-type-wp_template_part .block-editor-block-list__block[data-align=wide]>.block-editor-block-list__block-edit{margin-right:14px;margin-left:14px}@media (max-width:1200px){.post-type-page .wp-block:not([data-align=full]):not([data-align=wide]),.post-type-wp_template_part .wp-block:not([data-align=full]):not([data-align=wide]){max-width:580px}.post-type-page .is-sidebar-opened .wp-block:not([data-align=full]):not([data-align=wide]),.post-type-wp_template_part .is-sidebar-opened .wp-block:not([data-align=full]):not([data-align=wide]){max-width:400px}}.post-type-page .editor-writing-flow__click-redirect,.post-type-wp_template_part .editor-writing-flow__click-redirect{display:none}.editor-styles-wrapper{background:#fff}.post-type-page .edit-post-visual-editor{padding-top:0}.post-type-page .block-editor-writing-flow{display:block}.post-type-page .wp-block.template__block-container .wp-block-column [data-type="core/social-links"] [data-block]{margin:0}
 
trunk/full-site-editing/dist/full-site-editing.js DELETED
@@ -1,2 +0,0 @@
1
- /*! For license information please see full-site-editing.js.LICENSE */
2
- !function(e,t){for(var n in t)e[n]=t[n]}(window,function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(o,r,function(t){return e[t]}.bind(null,r));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=45)}([function(e,t){!function(){e.exports=this.wp.element}()},function(e,t){!function(){e.exports=this.wp.i18n}()},function(e,t){!function(){e.exports=this.wp.blockEditor}()},function(e,t){!function(){e.exports=this.wp.data}()},function(e,t){!function(){e.exports=this.wp.compose}()},function(e,t){!function(){e.exports=this.wp.components}()},function(e,t){e.exports=function(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}},function(e,t){!function(){e.exports=this.wp.blocks}()},function(e,t){!function(){e.exports=this.lodash}()},function(e,t,n){var o=n(6);function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,o)}return n}e.exports=function(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?r(Object(n),!0).forEach((function(t){o(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):r(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}},function(e,t){function n(){return e.exports=n=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var o in n)Object.prototype.hasOwnProperty.call(n,o)&&(e[o]=n[o])}return e},n.apply(this,arguments)}e.exports=n},function(e,t,n){var o;!function(){"use strict";var n={}.hasOwnProperty;function r(){for(var e=[],t=0;t<arguments.length;t++){var o=arguments[t];if(o){var i=typeof o;if("string"===i||"number"===i)e.push(o);else if(Array.isArray(o)&&o.length){var c=r.apply(null,o);c&&e.push(c)}else if("object"===i)for(var l in o)n.call(o,l)&&o[l]&&e.push(l)}}return e.join(" ")}e.exports?(r.default=r,e.exports=r):void 0===(o=function(){return r}.apply(t,[]))||(e.exports=o)}()},function(e,t){!function(){e.exports=this.wp.hooks}()},function(e,t,n){var o=n(34),r=n(35),i=n(36);e.exports=function(e,t){return o(e)||r(e,t)||i()}},function(e,t){!function(){e.exports=this.wp.domReady}()},function(e,t){!function(){e.exports=this.wp.apiFetch}()},function(e,t){!function(){e.exports=this.wp.htmlEntities}()},function(e,t,n){},function(e,t){!function(){e.exports=this.wp.serverSideRender}()},function(e,t){e.exports=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}},function(e,t){function n(e,t){for(var n=0;n<t.length;n++){var o=t[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}e.exports=function(e,t,o){return t&&n(e.prototype,t),o&&n(e,o),e}},function(e,t,n){var o=n(30),r=n(31);e.exports=function(e,t){return!t||"object"!==o(t)&&"function"!=typeof t?r(e):t}},function(e,t){function n(t){return e.exports=n=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)},n(t)}e.exports=n},function(e,t,n){var o=n(32);e.exports=function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&o(e,t)}},function(e,t){!function(){e.exports=this.wp.editor}()},function(e,t){!function(){e.exports=this.wp.url}()},function(e,t){!function(){e.exports=this.ReactDOM}()},function(e,t,n){var o=n(41),r=n(42),i=n(43);e.exports=function(e){return o(e)||r(e)||i()}},function(e,t){!function(){e.exports=this.wp.plugins}()},function(e,t,n){},function(e,t){function n(t){return"function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?e.exports=n=function(e){return typeof e}:e.exports=n=function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},n(t)}e.exports=n},function(e,t){e.exports=function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}},function(e,t){function n(t,o){return e.exports=n=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e},n(t,o)}e.exports=n},function(e,t,n){},function(e,t){e.exports=function(e){if(Array.isArray(e))return e}},function(e,t){e.exports=function(e,t){if(Symbol.iterator in Object(e)||"[object Arguments]"===Object.prototype.toString.call(e)){var n=[],o=!0,r=!1,i=void 0;try{for(var c,l=e[Symbol.iterator]();!(o=(c=l.next()).done)&&(n.push(c.value),!t||n.length!==t);o=!0);}catch(a){r=!0,i=a}finally{try{o||null==l.return||l.return()}finally{if(r)throw i}}return n}}},function(e,t){e.exports=function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t){e.exports=function(e){if(Array.isArray(e)){for(var t=0,n=new Array(e.length);t<e.length;t++)n[t]=e[t];return n}}},function(e,t){e.exports=function(e){if(Symbol.iterator in Object(e)||"[object Arguments]"===Object.prototype.toString.call(e))return Array.from(e)}},function(e,t){e.exports=function(){throw new TypeError("Invalid attempt to spread non-iterable instance")}},function(e,t,n){},function(e,t,n){"use strict";n.r(t);var o=n(0),r=n(7),i=n(1),c=n(10),l=n.n(c),a=n(18),s=n.n(a),u=n(4),p=n(2),d=n(5),b=n(3),f=Object(u.compose)([Object(p.withColors)("backgroundColor",{textColor:"color"}),Object(p.withFontSizes)("fontSize"),Object(b.withSelect)((function(e){return{isPublished:e("core/editor").isCurrentPostPublished()}}))])((function(e){var t=e.attributes,n=e.backgroundColor,r=e.fontSize,c=e.setAttributes,a=e.setBackgroundColor,u=e.setFontSize,b=e.setTextColor,f=e.textColor,m=e.isPublished,O=t.customFontSize,g=t.textAlign,j=O||r.size;return Object(o.createElement)(o.Fragment,null,Object(o.createElement)(p.BlockControls,null,Object(o.createElement)(p.AlignmentToolbar,{value:g,onChange:function(e){c({textAlign:e})}})),Object(o.createElement)(p.InspectorControls,null,Object(o.createElement)(d.PanelBody,{className:"blocks-font-size",title:Object(i.__)("Text Settings")},Object(o.createElement)(p.FontSizePicker,{onChange:u,value:j})),Object(o.createElement)(p.PanelColorSettings,{title:Object(i.__)("Color Settings"),initialOpen:!1,colorSettings:[{value:n.color,onChange:a,label:Object(i.__)("Background Color")},{value:f.color,onChange:b,label:Object(i.__)("Text Color")}]},Object(o.createElement)(p.ContrastChecker,l()({textColor:f.color,backgroundColor:n.color},{fontSize:j})))),Object(o.createElement)(s.a,{isPublished:m,block:"a8c/navigation-menu",attributes:t}))})),m=(n(29),Object(o.createElement)("svg",{xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24"},Object(o.createElement)("path",{fill:"none",d:"M0 0h24v24H0V0z"}),Object(o.createElement)("path",{d:"M12 7.27l4.28 10.43-3.47-1.53-.81-.36-.81.36-3.47 1.53L12 7.27M12 2L4.5 20.29l.71.71L12 18l6.79 3 .71-.71L12 2z"})));Object(r.registerBlockType)("a8c/navigation-menu",{title:Object(i.__)("Navigation Menu"),description:Object(i.__)("Visual placeholder for site-wide navigation and menus."),icon:m,category:"layout",supports:{align:["wide","full","right","left"],html:!1,reusable:!1},edit:f,save:function(){return null}});var O=n(12),g=n(6),j=n.n(g),v=n(19),h=n.n(v),y=n(20),_=n.n(y),S=n(21),E=n.n(S),k=n(22),w=n.n(k),C=n(23),x=n.n(C),P=n(11),T=n.n(P),B=n(24),I=function(e){function t(){return h()(this,t),E()(this,w()(t).apply(this,arguments))}return x()(t,e),_()(t,[{key:"toggleEditing",value:function(){var e=this.props,t=e.isEditing;(0,e.setState)({isEditing:!t})}},{key:"onSelectPost",value:function(e){var t=e.id,n=e.type;this.props.setState({isEditing:!1,selectedPostId:t,selectedPostType:n})}},{key:"render",value:function(){var e=this.props.attributes.align;return Object(o.createElement)(o.Fragment,null,Object(o.createElement)("div",{className:T()("post-content-block",j()({},"align".concat(e),e))},Object(o.createElement)(B.PostTitle,null),Object(o.createElement)(p.InnerBlocks,{templateLock:!1})))}}]),t}(o.Component),N=Object(u.compose)([Object(u.withState)({isEditing:!1,selectedPostId:void 0,selectedPostType:void 0}),Object(b.withSelect)((function(e,t){var n=t.selectedPostId,o=t.selectedPostType;return{selectedPost:(0,e("core").getEntityRecord)("postType",o,n)}}))])(I);n(33);Object(r.registerBlockType)("a8c/post-content",{title:Object(i.__)("Content"),description:Object(i.__)("The page content."),icon:"layout",category:"layout",supports:{align:["full"],anchor:!1,customClassName:!1,html:!1,inserter:!1,multiple:!1,reusable:!1},attributes:{align:{type:"string",default:"full"}},edit:N,save:function(){return Object(o.createElement)(p.InnerBlocks.Content,null)}});var A=Object(u.createHigherOrderComponent)((function(e){return function(t){return"a8c/post-content"!==t.name?Object(o.createElement)(e,t):Object(o.createElement)(e,l()({},t,{className:"post-content__block"}))}}),"addContentSlotClassname");Object(O.addFilter)("editor.BlockListBlock","full-site-editing/blocks/post-content",A,9);var z=n(9),D=n.n(z),F=n(13),L=n.n(F),R=n(15),V=n.n(R),M=n(16);function U(e){var t=Object(o.useRef)();return Object(o.useEffect)((function(){t.current=e}),[e]),t.current}function H(e,t,n,r,c,l){var a=Object(o.useState)({option:t,previousOption:"",loaded:!1,error:!1}),s=L()(a,2),u=s[0],p=s[1],d=U(r),b=U(c);function f(){p(D()({},u,{option:u.previousOption,isSaving:!1}))}return Object(o.useEffect)((function(){u.loaded||u.error?function(){var t=u.option,o=u.previousOption,l=!o&&!t||t&&o&&t.trim()===o.trim(),a=!t||0===t.trim().length;!r&&d&&a&&f();if(!c||l)return;!b&&c&&function(t){p(D()({},u,{isSaving:!0})),V()({path:"/wp/v2/settings",method:"POST",data:j()({},e,t)}).then((function(){return function(e){p(D()({},u,{previousOption:e,isDirty:!1,isSaving:!1}))}(t)})).catch((function(){n(Object(i.sprintf)(Object(i.__)("Unable to save site %s"),e)),f()}))}(t)}():V()({path:"/wp/v2/settings"}).then((function(t){return p(D()({},u,{option:Object(M.decodeEntities)(t[e]),previousOption:Object(M.decodeEntities)(t[e]),loaded:!0,error:!1}))})).catch((function(){n(Object(i.sprintf)(Object(i.__)("Unable to load site %s"),e)),p(D()({},u,{option:Object(i.sprintf)(Object(i.__)("Error loading site %s"),e),error:!0}))}))})),{siteOptions:u,handleChange:function(e){l({updated:Date.now()}),p(D()({},u,{option:e}))}}}var W=function(e){return Object(u.createHigherOrderComponent)((function(t){return Object(u.pure)((function(n){var r=Object(b.useSelect)((function(e){var t=e("core/editor"),n=t.isSavingPost,o=t.isPublishingPost,r=t.isAutosavingPost,i=t.isCurrentPostPublished;return(n()&&i()||o())&&!r()})),i=Object(b.useDispatch)((function(e){return e("core/notices").createErrorNotice})),c=n.isSelected,a=n.setAttributes,s=Object.keys(e).reduce((function(t,n){var o=e[n],l=H(o.optionName,o.defaultValue,i,c,r,a),s=l.siteOptions,u=l.handleChange;return t[n]={value:s.option,updateValue:u,loaded:s.loaded},t}),{});return Object(o.createElement)(t,l()({},n,s))}))}),"withSiteOptions")},q=fullSiteEditing.footerCreditOptions,G=function(e){var t=e.choice,n=q.find((function(e){return e.value===t}));if(!n)return null;var r=n.renderType,i=n.renderProps,c=n.label,l=D()({label:c},i);return"icon"===r?Object(o.createElement)(d.Icon,l):Object(o.createElement)("span",null," ",l.label," ")},Q=fullSiteEditing,Y=Q.footerCreditOptions,J=Q.defaultCreditOption;var K=Object(u.compose)([W({siteTitleOption:{optionName:"title",defaultValue:Object(i.__)("Site title loading…")},footerCreditOption:{optionName:"footer_credit",defaultValue:Object(i.__)("Footer credit loading…")}})])((function(e){var t=e.attributes.textAlign,n=void 0===t?"center":t,r=e.isSelected,i=e.setAttributes,c=e.footerCreditOption,l=c.value,a=c.updateValue,s=e.siteTitleOption.value,u=l||J;return Object(o.createElement)(o.Fragment,null,Object(o.createElement)(p.BlockControls,null,Object(o.createElement)(p.AlignmentToolbar,{value:n,onChange:function(e){i({textAlign:e})}})),Object(o.createElement)("div",{className:T()("site-info","site-credit__block",j()({},"has-text-align-".concat(n),n))},Object(o.createElement)("span",{className:"site-name"},s),Object(o.createElement)("span",{className:"comma"},","),Object(o.createElement)("span",{className:"site-credit__selection"},r?Object(o.createElement)(d.SelectControl,{onChange:a,value:u,options:Y}):Object(o.createElement)(G,{choice:u}))))}));n(37);Object(r.registerBlockType)("a8c/site-credit",{title:Object(i.__)("WordPress.com Credit"),description:Object(i.__)("This block tells the world that you're using WordPress.com."),icon:"wordpress-alt",category:"layout",supports:{align:["wide","full"],html:!1,multiple:!1,reusable:!1,removal:!1},attributes:{align:{type:"string",default:"wide"},textAlign:{type:"string",default:"center"}},edit:K,save:function(){return null}});var X=n(8);var Z=Object(u.compose)([Object(p.withColors)("backgroundColor",{textColor:"color"}),Object(p.withFontSizes)("fontSize"),Object(b.withSelect)((function(e,t){var n=t.clientId,o=e("core/block-editor"),r=o.getBlockIndex,i=o.getBlockRootClientId,c=o.getTemplateLock,l=i(n);return{blockIndex:r(n,l),isLocked:!!c(l),rootClientId:l}})),Object(b.withDispatch)((function(e,t){var n=t.blockIndex,o=t.rootClientId;return{insertDefaultBlock:function(){return e("core/block-editor").insertDefaultBlock({},o,n+1)}}})),W({siteDescription:{optionName:"description",defaultValue:Object(i.__)("Site description loading…")}})])((function(e){var t,n=e.attributes,r=e.backgroundColor,c=e.className,a=e.fontSize,s=e.insertDefaultBlock,u=e.setAttributes,b=e.setBackgroundColor,f=e.setFontSize,m=e.setTextColor,O=e.siteDescription,g=e.textColor,v=n.customFontSize,h=n.textAlign,y=v||a.size,_=O.value,S=O.updateValue;return Object(o.createElement)(o.Fragment,null,Object(o.createElement)(p.BlockControls,null,Object(o.createElement)(p.AlignmentToolbar,{value:h,onChange:function(e){u({textAlign:e})}})),Object(o.createElement)(p.InspectorControls,null,Object(o.createElement)(d.PanelBody,{className:"blocks-font-size",title:Object(i.__)("Text Settings")},Object(o.createElement)(p.FontSizePicker,{onChange:f,value:y})),Object(o.createElement)(p.PanelColorSettings,{title:Object(i.__)("Color Settings"),initialOpen:!1,colorSettings:[{value:r.color,onChange:b,label:Object(i.__)("Background Color")},{value:g.color,onChange:m,label:Object(i.__)("Text Color")}]},Object(o.createElement)(p.ContrastChecker,l()({textColor:g.color,backgroundColor:r.color},{fontSize:y})))),Object(o.createElement)(p.RichText,{allowedFormats:[],"aria-label":Object(i.__)("Site Description"),className:T()("site-description",c,(t={"has-text-color":g.color,"has-background":r.color},j()(t,"has-text-align-".concat(h),h),j()(t,r.class,r.class),j()(t,g.class,g.class),j()(t,a.class,!v&&a.class),t)),identifier:"content",onChange:S,onReplace:s,onSplit:X.noop,placeholder:Object(i.__)("Add a Site Description"),style:{backgroundColor:r.color,color:g.color,fontSize:y?y+"px":void 0},tagName:"p",value:_}))}));n(38);Object(r.registerBlockType)("a8c/site-description",{title:Object(i.__)("Site Description"),description:Object(i.__)("Site description, also known as the tagline."),icon:Object(o.createElement)("svg",{xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24"},Object(o.createElement)("path",{fill:"none",d:"M0 0h24v24H0z"}),Object(o.createElement)("path",{d:"M4 9h16v2H4V9zm0 4h10v2H4v-2z"})),category:"layout",supports:{align:["wide","full"],html:!1,multiple:!1,reusable:!1},attributes:{align:{type:"string",default:"wide"},textAlign:{type:"string",default:"center"},textColor:{type:"string"},customTextColor:{type:"string"},backgroundColor:{type:"string"},customBackgroundColor:{type:"string"},fontSize:{type:"string",default:"small"},customFontSize:{type:"number"}},edit:Z,save:function(){return null}});var $=Object(u.compose)([Object(p.withColors)({textColor:"color"}),Object(p.withFontSizes)("fontSize"),Object(b.withSelect)((function(e,t){var n=t.clientId,o=e("core/block-editor"),r=o.getBlockIndex,i=o.getBlockRootClientId,c=o.getTemplateLock,l=i(n);return{blockIndex:r(n,l),isLocked:!!c(l),rootClientId:l}})),Object(b.withDispatch)((function(e,t){var n=t.blockIndex,o=t.rootClientId;return{insertDefaultBlock:function(){return e("core/block-editor").insertDefaultBlock({},o,n+1)}}})),W({siteTitle:{optionName:"title",defaultValue:Object(i.__)("Site title loading…")}})])((function(e){var t,n=e.attributes,r=e.className,c=e.fontSize,l=e.insertDefaultBlock,a=e.setAttributes,s=e.setFontSize,u=e.setTextColor,b=e.siteTitle,f=e.textColor,m=n.customFontSize,O=n.textAlign,g=m||c.size,v=b.value,h=b.updateValue;return Object(o.createElement)(o.Fragment,null,Object(o.createElement)(p.BlockControls,null,Object(o.createElement)(p.AlignmentToolbar,{value:O,onChange:function(e){a({textAlign:e})}})),Object(o.createElement)(p.InspectorControls,null,Object(o.createElement)(d.PanelBody,{className:"blocks-font-size",title:Object(i.__)("Text Settings")},Object(o.createElement)(p.FontSizePicker,{onChange:s,value:g})),Object(o.createElement)(p.PanelColorSettings,{title:Object(i.__)("Color Settings"),initialOpen:!1,colorSettings:[{value:f.color,onChange:u,label:Object(i.__)("Text Color")}]})),Object(o.createElement)(p.RichText,{allowedFormats:[],"aria-label":Object(i.__)("Site Title"),className:T()("site-title",r,(t={"has-text-color":f.color},j()(t,"has-text-align-".concat(O),O),j()(t,f.class,f.class),j()(t,c.class,!m&&c.class),t)),identifier:"content",onChange:h,onReplace:l,onSplit:X.noop,placeholder:Object(i.__)("Add a Site Title"),style:{color:f.color,fontSize:g?g+"px":void 0},tagName:"h1",value:v}))}));n(39);Object(r.registerBlockType)("a8c/site-title",{title:Object(i.__)("Site Title"),description:Object(i.__)("Your site title."),icon:"layout",category:"layout",supports:{align:["wide","full"],html:!1,multiple:!1,reusable:!1},attributes:{align:{type:"string",default:"wide"},textAlign:{type:"string",default:"center"},textColor:{type:"string"},customTextColor:{type:"string"},fontSize:{type:"string",default:"normal"},customFontSize:{type:"number"}},edit:$,save:function(){return null}});var ee=n(25),te=(n(17),Object(u.compose)(Object(u.withState)({templateClientId:null}),Object(b.withSelect)((function(e,t){var n=t.attributes,o=t.templateClientId,r=e("core").getEntityRecord,i=e("core/editor"),c=i.getCurrentPostId,l=i.isEditedPostDirty,a=e("core/block-editor"),s=a.getBlock,u=a.getSelectedBlock,p=e("core/edit-post").isEditorSidebarOpened,d=n.templateId,b=c(),f=d&&r("postType","wp_template_part",d),m=Object(ee.addQueryArgs)(fullSiteEditing.editTemplateBaseUrl,{post:d,fse_parent_post:b}),O=u();return{currentPostId:b,editTemplateUrl:m,template:f,templateBlock:s(o),templateTitle:Object(X.get)(f,["title","rendered"],""),isDirty:l(),isEditorSidebarOpened:!!p(),isAnyTemplateBlockSelected:O&&"a8c/template"===O.name}})),Object(b.withDispatch)((function(e,t){var n=e("core/block-editor").receiveBlocks,o=e("core/edit-post").openGeneralSidebar,i=t.template,c=t.templateClientId,l=t.setState;return{savePost:e("core/editor").savePost,receiveTemplateBlocks:function(){if(i&&!c){var e=Object(r.parse)(Object(X.get)(i,["content","raw"],"")),t=Object(r.createBlock)("core/group",{},e);n([t]),l({templateClientId:t.clientId})}},openGeneralSidebar:o}})))((function(e){var t,n=e.attributes,r=e.editTemplateUrl,c=e.receiveTemplateBlocks,l=e.template,a=e.templateBlock,s=e.templateTitle,u=e.isDirty,b=e.savePost,f=e.isEditorSidebarOpened,m=e.openGeneralSidebar,O=e.isAnyTemplateBlockSelected;if(!l)return Object(o.createElement)(d.Placeholder,null,Object(o.createElement)(d.Spinner,null));var g=Object(o.createRef)(),v=Object(o.useState)(!1),h=L()(v,2),y=h[0],_=h[1];Object(o.useEffect)((function(){y&&!u&&g.current.click(),c()})),Object(o.useEffect)((function(){var e=document.querySelector(".edit-post-sidebar__panel-tabs ul li:last-child");if(f&&e){if(O)return m("edit-post/document"),void e.classList.add("hidden");e.classList.remove("hidden")}}),[O,f,m]);var S=n.align,E=n.className,k=function(e){e.stopPropagation(),_(!0),u&&(e.preventDefault(),b())};return Object(o.createElement)("div",{className:T()("template-block",(t={},j()(t,"align".concat(S),S),j()(t,"is-navigating-to-template",y),t))},a&&Object(o.createElement)(o.Fragment,null,Object(o.createElement)(d.Disabled,null,Object(o.createElement)("div",{className:E},Object(o.createElement)(p.BlockEdit,{attributes:a.attributes,block:a,clientId:a.clientId,isSelected:!1,name:a.name,setAttributes:X.noop}))),Object(o.createElement)(d.Placeholder,{className:"template-block__overlay",onClick:k},y&&Object(o.createElement)("div",{className:"template-block__loading"},Object(o.createElement)(d.Spinner,null)," ",Object(i.sprintf)(Object(i.__)("Loading editor for: %s"),s)),Object(o.createElement)(d.Button,{className:y?"hidden":null,href:r,onClick:k,isDefault:!0,isLarge:!0,ref:g},Object(i.sprintf)(Object(i.__)("Edit %s"),s)))))}))),ne=Object(u.createHigherOrderComponent)((function(e){return function(t){return"fse-site-logo"!==t.attributes.className?Object(o.createElement)(e,t):Object(o.createElement)(e,l()({},t,{className:"template__site-logo"}))}}),"addFSESiteLogoClassname");Object(O.addFilter)("editor.BlockListBlock","full-site-editing/blocks/template",ne),"wp_template_part"!==fullSiteEditing.editorPostType&&Object(r.registerBlockType)("a8c/template",{title:Object(i.__)("Template Part"),__experimentalDisplayName:"label",description:Object(i.__)("Display a Template Part."),icon:"layout",category:"layout",attributes:{templateId:{type:"number"},className:{type:"string"},label:{type:"string"}},supports:{anchor:!1,customClassName:!1,html:!1,inserter:!1,reusable:!1},edit:te,save:function(){return null},getEditWrapperProps:function(){return{"data-align":"full"}}});var oe=Object(u.createHigherOrderComponent)((function(e){return function(t){return"a8c/template"!==t.name?Object(o.createElement)(e,t):Object(o.createElement)(e,l()({},t,{className:"template__block-container"}))}}),"addFSETemplateClassname");Object(O.addFilter)("editor.BlockListBlock","full-site-editing/blocks/template",oe,9);var re=n(14),ie=n.n(re),ce=n(26),le=n.n(ce);n(40);function ae(e){var t=e.defaultLabel,n=e.defaultUrl,r=Object(o.useState)(t),i=L()(r,2),c=i[0],l=i[1],a=Object(o.useState)(n),s=L()(a,2),u=s[0],p=s[1];return window.wp.hooks.addAction("updateCloseButtonOverrides","a8c-fse",(function(e){l(e.label),p(e.closeUrl)})),Object(o.createElement)("a",{href:u,"aria-label":c},Object(o.createElement)(d.Button,{className:"components-button components-icon-button"},Object(o.createElement)(d.Dashicon,{icon:"arrow-left-alt2"}),Object(o.createElement)("div",{className:"close-button-override__label"},c)))}ie()((function(){var e=fullSiteEditing.editorPostType;if("wp_template_part"===e||"page"===e||"post"===e)var t=setInterval((function(){var n=document.querySelector(".edit-post-header__toolbar");if(n){clearInterval(t);var r=document.createElement("div");r.className="components-toolbar edit-post-fullscreen-mode-close__toolbar edit-post-fullscreen-mode-close__toolbar__override",n.prepend(r);var c=fullSiteEditing,l=c.closeButtonLabel,a=c.closeButtonUrl,s=window.calypsoifyGutenberg;s&&s.closeUrl&&(a=s.closeUrl),s&&s.closeButtonLabel&&(l=s.closeButtonLabel);var u=a||"edit.php?post_type=".concat(e),p=l||"Back";"page"!==e||l?"post"!==e||l?"wp_template_part"!==e||l||(p=Object(i.__)("Template Parts")):p=Object(i.__)("Posts"):p=Object(i.__)("Pages"),le.a.render(Object(o.createElement)(ae,{defaultLabel:p,defaultUrl:u}),r)}}))}));var se=n(27),ue=n.n(se),pe=n(28),de=Object(b.withSelect)((function(e){var t=e("core").getEntityRecord,n=e("core/editor").getEditedPostAttribute;return{templateClasses:Object(X.map)(n("template_part_types"),(function(e){var n=Object(X.get)(t("taxonomy","wp_template_part_type",e),"name","");return Object(X.endsWith)(n,"-header")?"fse-header":Object(X.endsWith)(n,"-footer")?"fse-footer":void 0}))}}))((function(e){var t=e.templateClasses,n=setInterval((function(){var e=document.querySelector(".block-editor-writing-flow.editor-writing-flow > div");e&&(clearInterval(n),e.className=T.a.apply(void 0,["a8c-template-editor fse-template-part"].concat(ue()(t))))}));return null}));"wp_template_part"===fullSiteEditing.editorPostType&&Object(pe.registerPlugin)("fse-editor-template-classes",{render:de}),ie()((function(){"wp_template_part"===fullSiteEditing.editorPostType&&Object(b.dispatch)("core/notices").createNotice("info",Object(i.__)("Updates to this template will affect all pages on your site."),{isDismissible:!1})}));var be=Object(u.compose)(Object(b.withSelect)((function(e){var t=e("core/editor").getEditorSettings,n=e("core/block-editor").getBlocks,o=e("core/edit-post").getEditorMode,r=n().find((function(e){return"a8c/post-content"===e.name}));return{rootClientId:r?r.clientId:"",showInserter:"visual"===o()&&t().richEditingEnabled}})))((function(e){var t=e.rootClientId,n=e.showInserter;return Object(o.createElement)(p.Inserter,{rootClientId:t,disabled:!n,position:"bottom right"})}));ie()((function(){return function(){if("page"===fullSiteEditing.editorPostType)var e=setInterval((function(){var t=document.querySelector(".edit-post-header-toolbar");if(t){clearInterval(e);var n=document.createElement("div");n.classList.add("fse-post-content-block-inserter"),t.insertBefore(n,t.firstChild),Object(o.render)(Object(o.createElement)(be,null),n)}}))}()}));var fe=Object(b.subscribe)((function(){if("page"!==fullSiteEditing.editorPostType)return fe();!1===Object(b.select)("core/block-editor").isValidTemplate()&&Object(b.dispatch)("core/block-editor").setTemplateValidity(!0)})),me=["logo","brand","emblem","hallmark"];Object(O.addFilter)("blocks.registerBlockType","full-site-editing/editor/image-block-keywords",(function(e,t){return"core/image"!==t?e:e=Object(X.assign)({},e,{keywords:e.keywords.concat(me)})}));n(44);Object(b.use)((function(e){return{dispatch:function(t){var n=D()({},e.dispatch(t)),o=fullSiteEditing.editorPostType;return"core/editor"===t&&n.trashPost&&"wp_template_part"===o&&(n.trashPost=function(){}),n}}})),Object(b.use)((function(e){return{dispatch:function(t){var n=D()({},e.dispatch(t)),o=fullSiteEditing.editorPostType;if("core/editor"===t&&n.editPost&&"wp_template_part"===o){var r=n.editPost;n.editPost=function(e){"draft"!==e.status&&r(e)}}return n}}}));var Oe=Object(b.subscribe)((function(){var e=Object(b.dispatch)("core/edit-post").removeEditorPanel;return"page"===fullSiteEditing.editorPostType&&e("featured-image"),"wp_template_part"===fullSiteEditing.editorPostType&&e("post-status"),Oe()}))}]));
 
 
trunk/full-site-editing/dist/full-site-editing.js.LICENSE DELETED
@@ -1,5 +0,0 @@
1
- /*!
2
- Copyright (c) 2017 Jed Watson.
3
- Licensed under the MIT License (MIT), see
4
- http://jedwatson.github.io/classnames
5
- */
 
 
 
 
 
trunk/full-site-editing/dist/full-site-editing.rtl.css DELETED
@@ -1 +0,0 @@
1
- .wp-block-a8c-navigation-menu.main-navigation{pointer-events:none}.post-content-block__selector{width:300px}.post-content-block__selector a{font-family:sans-serif;font-size:13px;padding-right:8px}.post-content-block__preview{pointer-events:none}.post-content-block__preview:after{content:"";clear:both;display:table}.post-content-block .editor-post-title,.show-post-title-before-content .editor-post-title{display:none}.show-post-title-before-content .post-content-block .editor-post-title{display:block}.block-editor-block-list__layout .post-content__block.is-selected .block-editor-block-contextual-toolbar{display:none}.block-editor-block-list__layout .post-content__block.block-editor-block-list__block.has-child-selected>.block-editor-block-list__block-edit:before,.block-editor-block-list__layout .post-content__block.block-editor-block-list__block.is-hovered>.block-editor-block-list__block-edit:before,.block-editor-block-list__layout .post-content__block.block-editor-block-list__block.is-navigate-mode>.block-editor-block-list__block-edit:before,.block-editor-block-list__layout .post-content__block.block-editor-block-list__block>.block-editor-block-list__block-edit:before{transition:none;border:none;outline:none;box-shadow:none}.block-editor-block-list__layout .post-content__block.block-editor-block-list__block.has-child-selected>.block-editor-block-list__block-edit>.block-editor-block-list__breadcrumb,.block-editor-block-list__layout .post-content__block.block-editor-block-list__block.is-hovered>.block-editor-block-list__block-edit>.block-editor-block-list__breadcrumb,.block-editor-block-list__layout .post-content__block.block-editor-block-list__block.is-navigate-mode>.block-editor-block-list__block-edit>.block-editor-block-list__breadcrumb,.block-editor-block-list__layout .post-content__block.block-editor-block-list__block>.block-editor-block-list__block-edit>.block-editor-block-list__breadcrumb{display:none}.site-credit__block{display:flex;flex-direction:row;align-items:center;font-size:14px;color:grey}.site-credit__block.has-text-align-center{justify-content:center}.site-credit__block.has-text-align-left{justify-content:flex-start}.site-credit__block.has-text-align-right{justify-content:flex-end}.site-credit__block .site-name{font-weight:700}.site-credit__block .site-credit__selection{margin-right:5px;display:flex;flex-direction:row;align-items:center}.site-credit__block .site-credit__selection .components-base-control .components-base-control__field{margin-bottom:0}.block-editor .wp-block-a8c-site-description:focus{box-shadow:none;background-color:transparent}.block-editor .wp-block.is-selected .wp-block-a8c-site-description::-webkit-input-placeholder{color:transparent}.block-editor .wp-block.is-selected .wp-block-a8c-site-description:-moz-placeholder,.block-editor .wp-block.is-selected .wp-block-a8c-site-description::-moz-placeholder{color:transparent}.block-editor .wp-block.is-selected .wp-block-a8c-site-description:-ms-input-placeholder{color:transparent}.block-editor .wp-block-a8c-site-title:focus{box-shadow:none;background-color:transparent}.block-editor .wp-block.is-selected .wp-block-a8c-site-title::-webkit-input-placeholder{color:transparent}.block-editor .wp-block.is-selected .wp-block-a8c-site-title:-moz-placeholder,.block-editor .wp-block.is-selected .wp-block-a8c-site-title::-moz-placeholder{color:transparent}.block-editor .wp-block.is-selected .wp-block-a8c-site-title:-ms-input-placeholder{color:transparent}.template-block{min-height:200px;overflow:hidden;position:relative}.post-type-page .editor-styles-wrapper .template-block .fse-template-part{padding:0}.template__block-container.is-hovered{cursor:pointer}.template__block-container.is-hovered .components-disabled,.template__block-container .is-navigating-to-template .components-disabled,.template__block-container.is-selected .components-disabled{filter:blur(2px);transition:filter .2s linear}.template__block-container.is-hovered .template-block__overlay,.template__block-container.is-hovered .template-block__overlay .components-button,.template__block-container .is-navigating-to-template .template-block__overlay,.template__block-container .is-navigating-to-template .template-block__overlay .components-button,.template__block-container.is-selected .template-block__overlay,.template__block-container.is-selected .template-block__overlay .components-button{opacity:1;transition:opacity .2s linear}.template__block-container .components-disabled{filter:blur(0);transition:filter .2s linear 0s}.template__block-container .block-editor-block-contextual-toolbar,.template__block-container .block-editor-block-list__block-edit:before,.template__block-container .block-editor-block-list__block-mobile-toolbar,.template__block-container .block-editor-block-list__breadcrumb,.template__block-container .block-editor-block-list__insertion-point{display:none}.template-block__overlay{background:hsla(0,0%,100%,.8);border:0 solid rgba(123,134,162,.3);bottom:0;right:0;margin:0;opacity:0;padding:0;position:absolute;left:0;transition:opacity .2s linear 0s;top:0;z-index:2}.is-selected .template-block__overlay{border-color:rgba(66,88,99,.4)}.editor-block-list__block:first-child .template-block__overlay{border-bottom-width:1px}.editor-block-list__block:last-child .template-block__overlay{border-top-width:1px}@media only screen and (min-width:768px){.template-block__overlay{border-width:1px}}.template-block__overlay .components-button{opacity:0;transition:opacity .2s linear 0s}.template-block__overlay .components-button.hidden{display:none}.template-block__loading{display:flex;align-items:center;color:#191e23}.block-editor-page:not(.post-type-wp_template_part) .fse-site-logo .components-placeholder__fieldset,.block-editor-page:not(.post-type-wp_template_part) .fse-site-logo .components-placeholder__instructions,.close-button-override-thin,.post-type-page .edit-post-fullscreen-mode-close__toolbar,.post-type-post .edit-post-fullscreen-mode-close__toolbar,.post-type-wp_template_part .edit-post-fullscreen-mode-close__toolbar{display:none}.post-type-page .edit-post-fullscreen-mode-close__toolbar__override,.post-type-post .edit-post-fullscreen-mode-close__toolbar__override,.post-type-wp_template_part .edit-post-fullscreen-mode-close__toolbar__override{display:flex;align-items:center;padding:9px 10px;margin-right:-8px;border:none;border-left:1px solid #e2e4e7}.post-type-page .edit-post-fullscreen-mode-close__toolbar__override a,.post-type-page .edit-post-fullscreen-mode-close__toolbar__override a:active,.post-type-page .edit-post-fullscreen-mode-close__toolbar__override a:hover,.post-type-page .edit-post-fullscreen-mode-close__toolbar__override a:link,.post-type-page .edit-post-fullscreen-mode-close__toolbar__override a:visited,.post-type-post .edit-post-fullscreen-mode-close__toolbar__override a,.post-type-post .edit-post-fullscreen-mode-close__toolbar__override a:active,.post-type-post .edit-post-fullscreen-mode-close__toolbar__override a:hover,.post-type-post .edit-post-fullscreen-mode-close__toolbar__override a:link,.post-type-post .edit-post-fullscreen-mode-close__toolbar__override a:visited,.post-type-wp_template_part .edit-post-fullscreen-mode-close__toolbar__override a,.post-type-wp_template_part .edit-post-fullscreen-mode-close__toolbar__override a:active,.post-type-wp_template_part .edit-post-fullscreen-mode-close__toolbar__override a:hover,.post-type-wp_template_part .edit-post-fullscreen-mode-close__toolbar__override a:link,.post-type-wp_template_part .edit-post-fullscreen-mode-close__toolbar__override a:visited{text-decoration:none}.post-type-page .edit-post-fullscreen-mode-close__toolbar__override .close-button-override__label,.post-type-post .edit-post-fullscreen-mode-close__toolbar__override .close-button-override__label,.post-type-wp_template_part .edit-post-fullscreen-mode-close__toolbar__override .close-button-override__label{font-size:13px}.post-type-page .edit-post-fullscreen-mode-close__toolbar__override .dashicons-arrow-left-alt2,.post-type-post .edit-post-fullscreen-mode-close__toolbar__override .dashicons-arrow-left-alt2,.post-type-wp_template_part .edit-post-fullscreen-mode-close__toolbar__override .dashicons-arrow-left-alt2{margin-right:-7px}@media (max-width:599px){.post-type-page .edit-post-fullscreen-mode-close__toolbar__override,.post-type-post .edit-post-fullscreen-mode-close__toolbar__override,.post-type-wp_template_part .edit-post-fullscreen-mode-close__toolbar__override{margin-right:-2px}}@media (max-width:400px){.post-type-page .edit-post-fullscreen-mode-close__toolbar__override .close-button-override-wide,.post-type-post .edit-post-fullscreen-mode-close__toolbar__override .close-button-override-wide,.post-type-wp_template_part .edit-post-fullscreen-mode-close__toolbar__override .close-button-override-wide{display:none}.post-type-page .edit-post-fullscreen-mode-close__toolbar__override .close-button-override-thin,.post-type-post .edit-post-fullscreen-mode-close__toolbar__override .close-button-override-thin,.post-type-wp_template_part .edit-post-fullscreen-mode-close__toolbar__override .close-button-override-thin{display:flex}.post-type-page .edit-post-fullscreen-mode-close__toolbar__override .close-button-override__label,.post-type-post .edit-post-fullscreen-mode-close__toolbar__override .close-button-override__label,.post-type-wp_template_part .edit-post-fullscreen-mode-close__toolbar__override .close-button-override__label{display:none}}.post-type-wp_template_part .edit-post-post-status,.post-type-wp_template_part .editor-post-title,.post-type-wp_template_part .editor-post-trash{display:none}.post-type-wp_template_part .edit-post-visual-editor{margin-top:20px;padding-top:0}.post-type-wp_template_part .editor-post-switch-to-draft{display:none}@media (min-width:768px){.post-type-page .edit-post-editor-regions__content,.post-type-page .edit-post-layout__content,.post-type-wp_template_part .edit-post-editor-regions__content,.post-type-wp_template_part .edit-post-layout__content{background:#eee}.post-type-page .edit-post-editor-regions__content .edit-post-visual-editor,.post-type-page .edit-post-layout__content .edit-post-visual-editor,.post-type-wp_template_part .edit-post-editor-regions__content .edit-post-visual-editor,.post-type-wp_template_part .edit-post-layout__content .edit-post-visual-editor{box-shadow:0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.12),0 1px 5px 0 rgba(0,0,0,.2);flex:none;margin:36px 32px}}.post-type-page .block-editor-block-list__layout,.post-type-wp_template_part .block-editor-block-list__layout{padding-right:0;padding-left:0}.post-type-page .block-editor-block-list__block[data-align=full]>.block-editor-block-list__block-edit,.post-type-wp_template_part .block-editor-block-list__block[data-align=full]>.block-editor-block-list__block-edit{margin-left:0;margin-right:0}.post-type-page .block-editor-block-list__block[data-align=wide]>.block-editor-block-list__block-edit,.post-type-wp_template_part .block-editor-block-list__block[data-align=wide]>.block-editor-block-list__block-edit{margin-left:14px;margin-right:14px}@media (max-width:1200px){.post-type-page .wp-block:not([data-align=full]):not([data-align=wide]),.post-type-wp_template_part .wp-block:not([data-align=full]):not([data-align=wide]){max-width:580px}.post-type-page .is-sidebar-opened .wp-block:not([data-align=full]):not([data-align=wide]),.post-type-wp_template_part .is-sidebar-opened .wp-block:not([data-align=full]):not([data-align=wide]){max-width:400px}}.post-type-page .editor-writing-flow__click-redirect,.post-type-wp_template_part .editor-writing-flow__click-redirect{display:none}.editor-styles-wrapper{background:#fff}.post-type-page .edit-post-visual-editor{padding-top:0}.post-type-page .block-editor-writing-flow{display:block}.post-type-page .wp-block.template__block-container .wp-block-column [data-type="core/social-links"] [data-block]{margin:0}
 
trunk/full-site-editing/editor/block-inserter/index.js DELETED
@@ -1,39 +0,0 @@
1
- /* global fullSiteEditing */
2
-
3
- /**
4
- * External dependencies
5
- */
6
- import domReady from '@wordpress/dom-ready';
7
- import { render } from '@wordpress/element';
8
-
9
- /**
10
- * Internal dependencies
11
- */
12
- import PostContentBlockAppender from './post-content-block-appender';
13
-
14
- /**
15
- * Renders a custom block inserter that will append new blocks inside the post content block.
16
- */
17
- function renderPostContentBlockInserter() {
18
- if ( 'page' !== fullSiteEditing.editorPostType ) {
19
- return;
20
- }
21
-
22
- const editPostHeaderToolbarInception = setInterval( () => {
23
- const headerToolbar = document.querySelector( '.edit-post-header-toolbar' );
24
-
25
- if ( ! headerToolbar ) {
26
- return;
27
- }
28
- clearInterval( editPostHeaderToolbarInception );
29
-
30
- const blockInserterContainer = document.createElement( 'div' );
31
- blockInserterContainer.classList.add( 'fse-post-content-block-inserter' );
32
-
33
- headerToolbar.insertBefore( blockInserterContainer, headerToolbar.firstChild );
34
-
35
- render( <PostContentBlockAppender />, blockInserterContainer );
36
- } );
37
- }
38
-
39
- domReady( () => renderPostContentBlockInserter() );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/editor/block-inserter/post-content-block-appender.js DELETED
@@ -1,27 +0,0 @@
1
- /**
2
- * External dependencies
3
- */
4
- import { Inserter } from '@wordpress/block-editor';
5
- import { compose } from '@wordpress/compose';
6
- import { withSelect } from '@wordpress/data';
7
-
8
- const PostContentBlockAppender = compose(
9
- withSelect( select => {
10
- const { getEditorSettings } = select( 'core/editor' );
11
- const { getBlocks } = select( 'core/block-editor' );
12
- const { getEditorMode } = select( 'core/edit-post' );
13
-
14
- const postContentBlock = getBlocks().find( block => block.name === 'a8c/post-content' );
15
-
16
- return {
17
- rootClientId: postContentBlock ? postContentBlock.clientId : '',
18
- showInserter: getEditorMode() === 'visual' && getEditorSettings().richEditingEnabled,
19
- };
20
- } )
21
- )( ( { rootClientId, showInserter } ) => {
22
- return (
23
- <Inserter rootClientId={ rootClientId } disabled={ ! showInserter } position="bottom right" />
24
- );
25
- } );
26
-
27
- export default PostContentBlockAppender;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/editor/image-block-keywords/index.js DELETED
@@ -1,23 +0,0 @@
1
- /**
2
- * External dependencies
3
- */
4
- import { assign } from 'lodash';
5
- import { addFilter } from '@wordpress/hooks';
6
-
7
- const additionalKeywords = [ 'logo', 'brand', 'emblem', 'hallmark' ];
8
-
9
- addFilter(
10
- 'blocks.registerBlockType',
11
- 'full-site-editing/editor/image-block-keywords',
12
- ( settings, name ) => {
13
- if ( name !== 'core/image' ) {
14
- return settings;
15
- }
16
-
17
- settings = assign( {}, settings, {
18
- keywords: settings.keywords.concat( additionalKeywords ),
19
- } );
20
-
21
- return settings;
22
- }
23
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/editor/index.js DELETED
@@ -1,10 +0,0 @@
1
- /**
2
- * Internal dependencies
3
- */
4
- import './block-inserter';
5
- import './template-validity-override';
6
- import './image-block-keywords';
7
- import './style.scss';
8
- import './suppress-trash-action';
9
- import './suppress-draft-action';
10
- import './remove-editor-panels';
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/editor/remove-editor-panels/index.js DELETED
@@ -1,31 +0,0 @@
1
- /* global fullSiteEditing */
2
-
3
- /**
4
- * External dependencies
5
- */
6
- import { dispatch, subscribe } from '@wordpress/data';
7
-
8
- /**
9
- * Disables specific sidebar editor panels in the FSE context.
10
- *
11
- * In particular, we remove the featured image panel for pages,
12
- * and we remove the post status panel for templates.
13
- *
14
- * Note that we only need to remove the panel once as it is persisted
15
- * in the redux state.
16
- */
17
- const unsubscribe = subscribe( () => {
18
- const { removeEditorPanel } = dispatch( 'core/edit-post' );
19
- if ( 'page' === fullSiteEditing.editorPostType ) {
20
- removeEditorPanel( 'featured-image' );
21
- }
22
-
23
- // @TODO Since the post status component doesn't check to see if it is removed, the
24
- // removeEditorPanel action won't have the desired effect. See:
25
- // https://github.com/WordPress/gutenberg/pull/17117
26
- // When support is added, we should remove the CSS hack at '../style.scss'
27
- if ( 'wp_template_part' === fullSiteEditing.editorPostType ) {
28
- removeEditorPanel( 'post-status' );
29
- }
30
- return unsubscribe();
31
- } );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/editor/style.scss DELETED
@@ -1,95 +0,0 @@
1
- .post-type-wp_template_part {
2
- .editor-post-title,
3
- .editor-post-trash {
4
- display: none;
5
- }
6
-
7
- // @TODO: Remove this when Gutenberg support is added for
8
- // removing the PostStatus panel:
9
- .edit-post-post-status {
10
- display: none;
11
- }
12
-
13
- .edit-post-visual-editor {
14
- margin-top: 20px;
15
- padding-top: 0;
16
- }
17
-
18
- .editor-post-switch-to-draft {
19
- display: none;
20
- }
21
- }
22
-
23
- .post-type-page,
24
- .post-type-wp_template_part {
25
- @media ( min-width: 768px ) {
26
- // @TODO: remove .edit-post-layout__content when Gutenberg 7.0.0 lands in production
27
- .edit-post-layout__content,
28
- .edit-post-editor-regions__content {
29
- background: #eee;
30
- }
31
-
32
- // @TODO: remove .edit-post-layout__content when Gutenberg 7.0.0 lands in production
33
- .edit-post-layout__content .edit-post-visual-editor,
34
- .edit-post-editor-regions__content .edit-post-visual-editor {
35
- box-shadow: 0 2px 2px 0 rgba( 0, 0, 0, 0.14 ), 0 3px 1px -2px rgba( 0, 0, 0, 0.12 ),
36
- 0 1px 5px 0 rgba( 0, 0, 0, 0.2 );
37
- flex: none;
38
- margin: 36px 32px;
39
- }
40
- }
41
-
42
- .block-editor-block-list__layout {
43
- padding-left: 0;
44
- padding-right: 0;
45
- }
46
-
47
- .block-editor-block-list__block[data-align='full'] > .block-editor-block-list__block-edit {
48
- margin-right: 0;
49
- margin-left: 0;
50
- }
51
-
52
- .block-editor-block-list__block[data-align='wide'] > .block-editor-block-list__block-edit {
53
- margin-right: 14px;
54
- margin-left: 14px;
55
- }
56
-
57
- @media ( max-width: 1200px ) {
58
- // Try to ensure that normally-aligned blocks work properly.
59
- .wp-block:not( [data-align='full'] ):not( [data-align='wide'] ) {
60
- max-width: 580px;
61
- }
62
- .is-sidebar-opened .wp-block:not( [data-align='full'] ):not( [data-align='wide'] ) {
63
- max-width: 400px;
64
- }
65
- }
66
-
67
- // Remove the 50vh bottom padding that looks off with the FSE frame.
68
- .editor-writing-flow__click-redirect {
69
- display: none;
70
- }
71
- }
72
-
73
- // We separate this from the other styles so that
74
- // the theme style can override this class without
75
- // having to get as specific.
76
- .editor-styles-wrapper {
77
- background: #fff;
78
- }
79
-
80
- .post-type-page {
81
- .edit-post-visual-editor {
82
- padding-top: 0;
83
- }
84
-
85
- .block-editor-writing-flow {
86
- display: block;
87
- }
88
-
89
- .wp-block.template__block-container
90
- .wp-block-column
91
- [data-type='core/social-links']
92
- [data-block] {
93
- margin: 0;
94
- }
95
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/editor/suppress-draft-action/index.js DELETED
@@ -1,38 +0,0 @@
1
- /* global fullSiteEditing */
2
-
3
- /**
4
- * External dependencies
5
- */
6
- import { use } from '@wordpress/data';
7
-
8
- // The purpose of this override is to prevent Switch to Draft action for template CPTs.
9
- use( registry => {
10
- return {
11
- dispatch: namespace => {
12
- const actions = { ...registry.dispatch( namespace ) };
13
- const { editorPostType } = fullSiteEditing;
14
-
15
- if (
16
- namespace === 'core/editor' &&
17
- actions.editPost &&
18
- editorPostType === 'wp_template_part'
19
- ) {
20
- const originalEditPost = actions.editPost;
21
-
22
- actions.editPost = edits => {
23
- const { status } = edits;
24
-
25
- // Bail if editPost is attempting to set draft as status.
26
- if ( status === 'draft' ) {
27
- return;
28
- }
29
-
30
- // Proceed with the usual call otherwise.
31
- originalEditPost( edits );
32
- };
33
- }
34
-
35
- return actions;
36
- },
37
- };
38
- } );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/editor/suppress-trash-action/index.js DELETED
@@ -1,26 +0,0 @@
1
- /* global fullSiteEditing */
2
-
3
- /**
4
- * External dependencies
5
- */
6
- import { use } from '@wordpress/data';
7
-
8
- // The purpose of this override is to prevent trash action from deleting template CPTs.
9
- use( registry => {
10
- return {
11
- dispatch: namespace => {
12
- const actions = { ...registry.dispatch( namespace ) };
13
- const { editorPostType } = fullSiteEditing;
14
-
15
- if (
16
- namespace === 'core/editor' &&
17
- actions.trashPost &&
18
- editorPostType === 'wp_template_part'
19
- ) {
20
- actions.trashPost = () => {};
21
- }
22
-
23
- return actions;
24
- },
25
- };
26
- } );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/editor/template-validity-override/index.js DELETED
@@ -1,23 +0,0 @@
1
- /* global fullSiteEditing */
2
-
3
- /**
4
- * External dependencies
5
- */
6
- import { select, dispatch, subscribe } from '@wordpress/data';
7
-
8
- /**
9
- * Forces the template validity.
10
- *
11
- * This is a work-around for the existing core issue that is showing a template mismatch warning when there is a parent
12
- * block with a locked template containing a nested InnerBlocks with an unlocked template.
13
- *
14
- * @see https://github.com/WordPress/gutenberg/issues/11681
15
- */
16
- const unsubscribe = subscribe( () => {
17
- if ( 'page' !== fullSiteEditing.editorPostType ) {
18
- return unsubscribe();
19
- }
20
- if ( select( 'core/block-editor' ).isValidTemplate() === false ) {
21
- dispatch( 'core/block-editor' ).setTemplateValidity( true );
22
- }
23
- } );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/helpers.php DELETED
@@ -1,181 +0,0 @@
1
- <?php
2
- /**
3
- * Helpers for Full Site Editing.
4
- *
5
- * This file is always loaded, so these functions should always exist if the
6
- * plugin is activated on the site. (Not to be confused with whether FSE is
7
- * active on the site!)
8
- *
9
- * @package A8C\FSE
10
- */
11
-
12
- namespace A8C\FSE;
13
-
14
- /**
15
- * NOTE: In most cases, you should NOT use this function. Please use
16
- * load_full_site_editing instead. This function should only be used if you need
17
- * to include the FSE files somewhere like a script. I.e. if you want to access
18
- * a class defined here without needing full FSE functionality.
19
- */
20
- function dangerously_load_full_site_editing_files() {
21
- require_once __DIR__ . '/blocks/navigation-menu/index.php';
22
- require_once __DIR__ . '/blocks/post-content/index.php';
23
- require_once __DIR__ . '/blocks/site-description/index.php';
24
- require_once __DIR__ . '/blocks/site-title/index.php';
25
- require_once __DIR__ . '/blocks/template/index.php';
26
- require_once __DIR__ . '/class-full-site-editing.php';
27
- require_once __DIR__ . '/templates/class-rest-templates-controller.php';
28
- require_once __DIR__ . '/templates/class-wp-template.php';
29
- require_once __DIR__ . '/templates/class-wp-template-inserter.php';
30
- require_once __DIR__ . '/templates/class-template-image-inserter.php';
31
- require_once __DIR__ . '/serialize-block-fallback.php';
32
- }
33
-
34
- /**
35
- * Whether or not FSE is active.
36
- * If false, FSE functionality should be disabled.
37
- *
38
- * @returns bool True if FSE is active, false otherwise.
39
- */
40
- function is_full_site_editing_active() {
41
- /**
42
- * There are times when this function is called from the WordPress.com public
43
- * API context. In this case, we need to switch to the correct blog so that
44
- * the functions reference the correct blog context.
45
- */
46
- $multisite_id = apply_filters( 'a8c_fse_get_multisite_id', false );
47
- $should_switch = is_multisite() && $multisite_id;
48
- if ( $should_switch ) {
49
- switch_to_blog( $multisite_id );
50
- }
51
-
52
- $is_active = is_site_eligible_for_full_site_editing() && is_theme_supported() && did_insert_template_parts();
53
-
54
- if ( $should_switch ) {
55
- restore_current_blog();
56
- }
57
- return $is_active;
58
- }
59
-
60
- /**
61
- * Returns the slug for the current theme.
62
- *
63
- * This even works for the WordPress.com API context where the current theme is
64
- * not correct. The filter correctly switches to the correct blog context if
65
- * that is the case.
66
- *
67
- * @return string Theme slug.
68
- */
69
- function get_theme_slug() {
70
- /**
71
- * Used to get the correct theme in certain contexts.
72
- *
73
- * For example, in the wpcom API context, the theme slug is a8c/public-api,
74
- * so we need to grab the correct one with the filter.
75
- *
76
- * @since 0.7
77
- *
78
- * @param string current theme slug is the default if nothing overrides it.
79
- */
80
- return apply_filters( 'a8c_fse_get_theme_slug', get_stylesheet() );
81
- }
82
-
83
- /**
84
- * Returns a normalized slug for the current theme.
85
- *
86
- * In some cases, the theme is located in a subfolder like `pub/maywood`. Use
87
- * this function to get the slug without the prefix.
88
- *
89
- * @param string $theme_slug The raw theme_slug to normalize.
90
- * @return string Theme slug.
91
- */
92
- function normalize_theme_slug( $theme_slug ) {
93
- // Normalize the theme slug.
94
- if ( 'pub/' === substr( $theme_slug, 0, 4 ) ) {
95
- $theme_slug = substr( $theme_slug, 4 );
96
- }
97
-
98
- if ( '-wpcom' === substr( $theme_slug, -6, 6 ) ) {
99
- $theme_slug = substr( $theme_slug, 0, -6 );
100
- }
101
-
102
- return $theme_slug;
103
- }
104
-
105
- /**
106
- * Whether or not the site is eligible for FSE. This is essentially a feature
107
- * gate to disable FSE on some sites which could theoretically otherwise use it.
108
- *
109
- * @return bool True if current site is eligible for FSE, false otherwise.
110
- */
111
- function is_site_eligible_for_full_site_editing() {
112
- /**
113
- * Can be used to disable Full Site Editing functionality.
114
- *
115
- * @since 0.2
116
- *
117
- * @param bool true if Full Site Editing should be disabled, false otherwise.
118
- */
119
- return ! apply_filters( 'a8c_disable_full_site_editing', false );
120
- }
121
-
122
- /**
123
- * Whether or not current theme is enabled for FSE.
124
- *
125
- * @return bool True if current theme supports FSE, false otherwise.
126
- */
127
- function is_theme_supported() {
128
- // Use un-normalized theme slug because get_theme requires the full string.
129
- $theme = wp_get_theme( get_theme_slug() );
130
- return ! $theme->errors() && in_array( 'full-site-editing', $theme->tags, true );
131
- }
132
-
133
- /**
134
- * Determines if the template parts have been inserted for the current theme.
135
- *
136
- * We want to gate on this check in is_full_site_editing_active so that we don't
137
- * load FSE for sites which did not get template parts for some reason or another.
138
- *
139
- * For example, if a user activates theme A on their site and gets FSE, but then
140
- * activates theme B which does not have FSE, they will not get FSE flows. If we
141
- * retroactively add FSE support to theme B, the user should not get FSE flows
142
- * because their site would be modified. Instead, FSE flows would become active
143
- * when they specifically take action to re-activate the theme.
144
- *
145
- * @return bool True if the template parts have been inserted. False otherwise.
146
- */
147
- function did_insert_template_parts() {
148
- require_once __DIR__ . '/templates/class-wp-template-inserter.php';
149
-
150
- $theme_slug = normalize_theme_slug( get_theme_slug() );
151
- $inserter = new WP_Template_Inserter( $theme_slug );
152
- return $inserter->is_template_data_inserted();
153
- }
154
-
155
- /**
156
- * Inserts default full site editing data for current theme on plugin/theme activation.
157
- *
158
- * We put this here outside of the normal FSE class because FSE is not active
159
- * until the template parts are inserted. This makes sure we insert the template
160
- * parts when switching to a theme which supports FSE.
161
- *
162
- * This will populate the default header and footer for current theme, and create
163
- * About and Contact pages. Nothing will populate if the data already exists, or
164
- * if the theme is unsupported.
165
- */
166
- function populate_wp_template_data() {
167
- if ( ! is_theme_supported() ) {
168
- return;
169
- }
170
-
171
- require_once __DIR__ . '/templates/class-template-image-inserter.php';
172
- require_once __DIR__ . '/templates/class-wp-template-inserter.php';
173
-
174
- $theme_slug = normalize_theme_slug( get_theme_slug() );
175
-
176
- $template_inserter = new WP_Template_Inserter( $theme_slug );
177
- $template_inserter->insert_default_template_data();
178
- $template_inserter->insert_default_pages();
179
- }
180
- register_activation_hook( __FILE__, __NAMESPACE__ . '\populate_wp_template_data' );
181
- add_action( 'switch_theme', __NAMESPACE__ . '\populate_wp_template_data' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/index.js DELETED
@@ -1,13 +0,0 @@
1
- /**
2
- * Internal dependencies
3
- */
4
- import './blocks/navigation-menu';
5
- import './blocks/post-content';
6
- import './blocks/site-credit';
7
- import './blocks/site-description';
8
- import './blocks/site-title';
9
- import './blocks/template';
10
- import './plugins/close-button-override';
11
- import './plugins/editor-template-classes';
12
- import './plugins/template-update-notice';
13
- import './editor';
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/lib/index.js DELETED
@@ -1 +0,0 @@
1
- export * from './site-options';
 
trunk/full-site-editing/lib/site-options/index.js DELETED
@@ -1,2 +0,0 @@
1
- export * from './use-site-options';
2
- export * from './with-site-options';
 
 
trunk/full-site-editing/lib/site-options/use-previous.js DELETED
@@ -1,24 +0,0 @@
1
- /* eslint-disable import/no-extraneous-dependencies */
2
-
3
- /**
4
- * External dependencies
5
- */
6
- import { useEffect, useRef } from '@wordpress/element';
7
-
8
- /**
9
- * Custom hook to provide the previous value of state or props in a functional component
10
- *
11
- * see https://reactjs.org/docs/hooks-faq.html#how-to-get-the-previous-props-or-state
12
- *
13
- * @param {any} value state or prop value for which previous value is required
14
- * @return {any} previous value of requested state or prop value
15
- */
16
- export function usePrevious( value ) {
17
- const ref = useRef();
18
-
19
- useEffect( () => {
20
- ref.current = value;
21
- }, [ value ] );
22
-
23
- return ref.current;
24
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/lib/site-options/use-site-options.js DELETED
@@ -1,127 +0,0 @@
1
- /* eslint-disable import/no-extraneous-dependencies */
2
-
3
- /**
4
- * External dependencies
5
- */
6
- import { __, sprintf } from '@wordpress/i18n';
7
- import { useState, useEffect } from '@wordpress/element';
8
- import apiFetch from '@wordpress/api-fetch';
9
- import { decodeEntities } from '@wordpress/html-entities';
10
-
11
- /**
12
- * Internal dependencies
13
- */
14
- import { usePrevious } from './use-previous';
15
-
16
- export function useSiteOptions(
17
- siteOption,
18
- inititalOption,
19
- createErrorNotice,
20
- isSelected,
21
- shouldUpdateSiteOption,
22
- setAttributes
23
- ) {
24
- const [ siteOptions, setSiteOptions ] = useState( {
25
- option: inititalOption,
26
- previousOption: '',
27
- loaded: false,
28
- error: false,
29
- } );
30
-
31
- const previousIsSelected = usePrevious( isSelected );
32
- const previousShouldUpdateSiteOption = usePrevious( shouldUpdateSiteOption );
33
-
34
- useEffect( () => {
35
- if ( ! siteOptions.loaded && ! siteOptions.error ) {
36
- loadSiteOption();
37
- } else {
38
- updateSiteOption();
39
- }
40
- } );
41
-
42
- function loadSiteOption() {
43
- apiFetch( { path: '/wp/v2/settings' } )
44
- .then( result =>
45
- setSiteOptions( {
46
- ...siteOptions,
47
- option: decodeEntities( result[ siteOption ] ),
48
- previousOption: decodeEntities( result[ siteOption ] ),
49
- loaded: true,
50
- error: false,
51
- } )
52
- )
53
- .catch( () => {
54
- createErrorNotice( sprintf( __( 'Unable to load site %s' ), siteOption ) );
55
- setSiteOptions( {
56
- ...siteOptions,
57
- option: sprintf( __( 'Error loading site %s' ), siteOption ),
58
- error: true,
59
- } );
60
- } );
61
- }
62
-
63
- function updateSiteOption() {
64
- const { option, previousOption } = siteOptions;
65
-
66
- /**
67
- * 1. Both `previousOption` and `option` are falsey.
68
- * OR
69
- * 2. Both `previousOption` and `option` are the same value after trim.
70
- */
71
- const optionUnchanged =
72
- ( ! previousOption && ! option ) ||
73
- ( option && previousOption && option.trim() === previousOption.trim() );
74
- const optionIsEmpty = ! option || option.trim().length === 0;
75
-
76
- // Reset to initial value if user de-selects the block with an empty value.
77
- if ( ! isSelected && previousIsSelected && optionIsEmpty ) {
78
- revertOption();
79
- }
80
-
81
- // Don't do anything further if we shouldn't update the site option or the value is unchanged.
82
- if ( ! shouldUpdateSiteOption || optionUnchanged ) {
83
- return;
84
- }
85
-
86
- if ( ! previousShouldUpdateSiteOption && shouldUpdateSiteOption ) {
87
- saveSiteOption( option );
88
- }
89
- }
90
-
91
- function saveSiteOption( option ) {
92
- setSiteOptions( { ...siteOptions, isSaving: true } );
93
- apiFetch( { path: '/wp/v2/settings', method: 'POST', data: { [ siteOption ]: option } } )
94
- .then( () => updatePreviousOption( option ) )
95
- .catch( () => {
96
- createErrorNotice( sprintf( __( 'Unable to save site %s' ), siteOption ) );
97
- revertOption();
98
- } );
99
- }
100
-
101
- function revertOption() {
102
- setSiteOptions( {
103
- ...siteOptions,
104
- option: siteOptions.previousOption,
105
- isSaving: false,
106
- } );
107
- }
108
-
109
- function updatePreviousOption( option ) {
110
- setSiteOptions( {
111
- ...siteOptions,
112
- previousOption: option,
113
- isDirty: false,
114
- isSaving: false,
115
- } );
116
- }
117
-
118
- function handleChange( value ) {
119
- // The following is a temporary fix. Setting this fake attribute is used to flag
120
- // the content as dirty to editor and enable Update/Publish button. This should be
121
- // removed once updating of site options handled in core editor
122
- setAttributes( { updated: Date.now() } );
123
- setSiteOptions( { ...siteOptions, option: value } );
124
- }
125
-
126
- return { siteOptions, handleChange };
127
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/lib/site-options/with-site-options.js DELETED
@@ -1,99 +0,0 @@
1
- /* eslint-disable import/no-extraneous-dependencies */
2
- /**
3
- * External dependencies
4
- */
5
- import { createHigherOrderComponent, pure } from '@wordpress/compose';
6
- import { useSelect, useDispatch } from '@wordpress/data';
7
-
8
- /**
9
- * Internal dependencies
10
- */
11
- import { useSiteOptions } from './use-site-options';
12
-
13
- /**
14
- * Higher Order Component used to inject site options.
15
- *
16
- * The option value is requested from the WordPress API. Note that arbitrary
17
- * options can only be retrieved if they have been registered as site settings.
18
- *
19
- * Updates are persisted to the database when the post is saved.
20
- *
21
- * In the component, every specified `optionName` will be a prop which maps to
22
- * an object with the keys `value`, `updateValue`, and `loaded`. `value`
23
- * contains the actual value of the WordPress option, and `updateValue` can be
24
- * used to update the option. `updateValue` will re-render the component with
25
- * the new `value`.
26
- *
27
- * @param {Object} options An object of site options to retrieve. Keys should be
28
- * option names you wish to have locally. They can be
29
- * named whatever makes sense in the context of your
30
- * component. Any key's value should be another object
31
- * whih contains `optionName`, the actual name of the
32
- * WordPress option to fetch, and `defaultValue`, the
33
- * value to use while the option is fetching.
34
- *
35
- * @return {Component} The higher order component.
36
- *
37
- * In the following example, withSiteOptions is called with an object mapping a
38
- * name for the option to some information about it. In particular, optionName
39
- * needs to match the name of the option in WordPress, and defaultValue is used
40
- * while the option is loading from the API.
41
- *
42
- * @example
43
- * function Component( { mySiteOption } ) {
44
- * const { value, updateValue } = mySiteOption;
45
- * // `updateValue( 'foo' )` the component will re-render if called.
46
- * return <span>{ value }</span>;
47
- * }
48
- *
49
- * export default compose( [
50
- * withSiteOptions( {
51
- * mySiteOption: { optionName: 'title', defaultValue: __( 'Site title loading…' ) },
52
- * } ),
53
- * ] )( Component );
54
- *
55
- */
56
- export const withSiteOptions = options =>
57
- createHigherOrderComponent(
58
- WrappedComponent =>
59
- pure( ownProps => {
60
- const shouldUpdateSiteOption = useSelect( select => {
61
- const {
62
- isSavingPost,
63
- isPublishingPost,
64
- isAutosavingPost,
65
- isCurrentPostPublished,
66
- } = select( 'core/editor' );
67
- return (
68
- ( ( isSavingPost() && isCurrentPostPublished() ) || isPublishingPost() ) &&
69
- ! isAutosavingPost()
70
- );
71
- } );
72
-
73
- const createErrorNotice = useDispatch(
74
- dispatch => dispatch( 'core/notices' ).createErrorNotice
75
- );
76
-
77
- const { isSelected, setAttributes } = ownProps;
78
- const allOptions = Object.keys( options ).reduce( ( accumulator, name ) => {
79
- const { optionName, defaultValue } = options[ name ];
80
- const { siteOptions, handleChange } = useSiteOptions(
81
- optionName,
82
- defaultValue,
83
- createErrorNotice,
84
- isSelected,
85
- shouldUpdateSiteOption,
86
- setAttributes
87
- );
88
- accumulator[ name ] = {
89
- value: siteOptions.option,
90
- updateValue: handleChange,
91
- loaded: siteOptions.loaded,
92
- };
93
- return accumulator;
94
- }, {} );
95
-
96
- return <WrappedComponent { ...ownProps } { ...allOptions } />;
97
- } ),
98
- 'withSiteOptions'
99
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/plugins/close-button-override/index.js DELETED
@@ -1,100 +0,0 @@
1
- /* global fullSiteEditing */
2
-
3
- /**
4
- * External dependencies
5
- */
6
- /* eslint-disable import/no-extraneous-dependencies */
7
- import domReady from '@wordpress/dom-ready';
8
- import ReactDOM from 'react-dom';
9
- import { __ } from '@wordpress/i18n';
10
- import { Button, Dashicon } from '@wordpress/components';
11
- import { useState } from '@wordpress/element';
12
- /* eslint-disable import/no-extraneous-dependencies */
13
-
14
- /**
15
- * Internal dependencies
16
- */
17
- import './style.scss';
18
-
19
- function BackButtonOverride( { defaultLabel, defaultUrl } ) {
20
- const [ label, updateLabel ] = useState( defaultLabel );
21
- const [ url, updateUrl ] = useState( defaultUrl );
22
- window.wp.hooks.addAction( 'updateCloseButtonOverrides', 'a8c-fse', data => {
23
- updateLabel( data.label );
24
- updateUrl( data.closeUrl );
25
- } );
26
-
27
- return (
28
- <a href={ url } aria-label={ label }>
29
- { /* eslint-disable-next-line wpcalypso/jsx-classname-namespace */ }
30
- <Button className="components-button components-icon-button">
31
- <Dashicon icon="arrow-left-alt2" />
32
- <div className="close-button-override__label">{ label }</div>
33
- </Button>
34
- </a>
35
- );
36
- }
37
-
38
- domReady( () => {
39
- const { editorPostType } = fullSiteEditing;
40
-
41
- // Only alter for the page, post, and template part editors.
42
- if (
43
- 'wp_template_part' !== editorPostType &&
44
- 'page' !== editorPostType &&
45
- 'post' !== editorPostType
46
- ) {
47
- return;
48
- }
49
-
50
- const editPostHeaderInception = setInterval( () => {
51
- // Cycle through interval until header toolbar is found.
52
- const toolbar = document.querySelector( '.edit-post-header__toolbar' );
53
-
54
- if ( ! toolbar ) {
55
- return;
56
- }
57
- clearInterval( editPostHeaderInception );
58
-
59
- // Add components toolbar with override class name (original will be hidden in ./style.scss).
60
- const componentsToolbar = document.createElement( 'div' );
61
- componentsToolbar.className =
62
- 'components-toolbar edit-post-fullscreen-mode-close__toolbar edit-post-fullscreen-mode-close__toolbar__override';
63
- toolbar.prepend( componentsToolbar );
64
-
65
- // These should go here so that they have any updates that happened while querying for the selector.
66
- let { closeButtonLabel, closeButtonUrl } = fullSiteEditing;
67
-
68
- /**
69
- * We have to reference calypsoifyGutenberg off of the window object
70
- * directly to handle the case where it is undefined. Otherwise, the
71
- * variable declariation itself won't exist, causing a runtime error.
72
- */
73
- const { calypsoifyGutenberg } = window;
74
-
75
- // Use wpcom close button/url if they exist.
76
- if ( calypsoifyGutenberg && calypsoifyGutenberg.closeUrl ) {
77
- closeButtonUrl = calypsoifyGutenberg.closeUrl;
78
- }
79
-
80
- if ( calypsoifyGutenberg && calypsoifyGutenberg.closeButtonLabel ) {
81
- closeButtonLabel = calypsoifyGutenberg.closeButtonLabel;
82
- }
83
-
84
- const defaultUrl = closeButtonUrl || `edit.php?post_type=${ editorPostType }`;
85
-
86
- let defaultLabel = closeButtonLabel || 'Back';
87
- if ( 'page' === editorPostType && ! closeButtonLabel ) {
88
- defaultLabel = __( 'Pages' );
89
- } else if ( 'post' === editorPostType && ! closeButtonLabel ) {
90
- defaultLabel = __( 'Posts' );
91
- } else if ( 'wp_template_part' === editorPostType && ! closeButtonLabel ) {
92
- defaultLabel = __( 'Template Parts' );
93
- }
94
-
95
- ReactDOM.render(
96
- <BackButtonOverride defaultLabel={ defaultLabel } defaultUrl={ defaultUrl } />,
97
- componentsToolbar
98
- );
99
- } );
100
- } );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/plugins/close-button-override/style.scss DELETED
@@ -1,50 +0,0 @@
1
- .post-type-wp_template_part .edit-post-fullscreen-mode-close__toolbar,
2
- .post-type-page .edit-post-fullscreen-mode-close__toolbar,
3
- .post-type-post .edit-post-fullscreen-mode-close__toolbar,
4
- .close-button-override-thin {
5
- display: none;
6
- }
7
-
8
- .post-type-wp_template_part .edit-post-fullscreen-mode-close__toolbar__override,
9
- .post-type-page .edit-post-fullscreen-mode-close__toolbar__override,
10
- .post-type-post .edit-post-fullscreen-mode-close__toolbar__override {
11
- display: flex;
12
- align-items: center;
13
- padding: 9px 10px;
14
- margin-left: -8px;
15
- border: none;
16
- border-right: 1px solid #e2e4e7;
17
-
18
- a,
19
- a:link,
20
- a:visited,
21
- a:hover,
22
- a:active {
23
- text-decoration: none;
24
- }
25
-
26
- .close-button-override__label {
27
- font-size: 13px;
28
- }
29
-
30
- .dashicons-arrow-left-alt2 {
31
- margin-left: -7px;
32
- }
33
-
34
- @media ( max-width: 599px ) {
35
- margin-left: -2px;
36
- }
37
-
38
- @media ( max-width: 400px ) {
39
- .close-button-override-wide {
40
- display: none;
41
- }
42
- .close-button-override-thin {
43
- display: flex;
44
- }
45
- .close-button-override__label {
46
- display: none;
47
- }
48
- }
49
- }
50
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/plugins/editor-template-classes/index.js DELETED
@@ -1,53 +0,0 @@
1
- /* eslint-disable import/no-extraneous-dependencies */
2
- /* global fullSiteEditing */
3
- /**
4
- * External dependencies
5
- */
6
- import classNames from 'classnames';
7
- import { endsWith, get, map } from 'lodash';
8
-
9
- /**
10
- * WordPress dependencies
11
- */
12
- import { withSelect } from '@wordpress/data';
13
- import { registerPlugin } from '@wordpress/plugins';
14
-
15
- const EditorTemplateClasses = withSelect( select => {
16
- const { getEntityRecord } = select( 'core' );
17
- const { getEditedPostAttribute } = select( 'core/editor' );
18
- const templateClasses = map( getEditedPostAttribute( 'template_part_types' ), typeId => {
19
- const typeName = get(
20
- getEntityRecord( 'taxonomy', 'wp_template_part_type', typeId ),
21
- 'name',
22
- ''
23
- );
24
- if ( endsWith( typeName, '-header' ) ) {
25
- return 'fse-header';
26
- }
27
- if ( endsWith( typeName, '-footer' ) ) {
28
- return 'fse-footer';
29
- }
30
- } );
31
- return { templateClasses };
32
- } )( ( { templateClasses } ) => {
33
- const blockListInception = setInterval( () => {
34
- const blockList = document.querySelector(
35
- '.block-editor-writing-flow.editor-writing-flow > div'
36
- );
37
-
38
- if ( ! blockList ) {
39
- return;
40
- }
41
- clearInterval( blockListInception );
42
-
43
- blockList.className = classNames( 'a8c-template-editor fse-template-part', ...templateClasses );
44
- } );
45
-
46
- return null;
47
- } );
48
-
49
- if ( 'wp_template_part' === fullSiteEditing.editorPostType ) {
50
- registerPlugin( 'fse-editor-template-classes', {
51
- render: EditorTemplateClasses,
52
- } );
53
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/plugins/template-update-notice/index.js DELETED
@@ -1,20 +0,0 @@
1
- /* global fullSiteEditing */
2
- /**
3
- * External dependencies
4
- */
5
- import domReady from '@wordpress/dom-ready';
6
- import { dispatch } from '@wordpress/data';
7
- import { __ } from '@wordpress/i18n';
8
-
9
- domReady( () => {
10
- if ( 'wp_template_part' !== fullSiteEditing.editorPostType ) {
11
- return;
12
- }
13
- dispatch( 'core/notices' ).createNotice(
14
- 'info',
15
- __( 'Updates to this template will affect all pages on your site.' ),
16
- {
17
- isDismissible: false,
18
- }
19
- );
20
- } );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/sass/_mixins.scss DELETED
@@ -1,17 +0,0 @@
1
- @mixin hide-input-placeholder {
2
- &::-webkit-input-placeholder {
3
- color: transparent;
4
- }
5
-
6
- &:-moz-placeholder {
7
- color: transparent;
8
- }
9
-
10
- &::-moz-placeholder {
11
- color: transparent;
12
- }
13
-
14
- &:-ms-input-placeholder {
15
- color: transparent;
16
- }
17
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/serialize-block-fallback.php DELETED
@@ -1,70 +0,0 @@
1
- <?php
2
- /**
3
- * Fallback to provide serialize_block support being added to WP 5.3.0
4
- *
5
- * @package A8C\FSE
6
- */
7
-
8
- if ( ! function_exists( 'serialize_block' ) ) {
9
- /**
10
- * Renders an HTML-serialized form of a block object
11
- * from https://core.trac.wordpress.org/ticket/47375
12
- *
13
- * Should be available since WordPress 5.3.0.
14
- *
15
- * @param array $block The block being rendered.
16
- * @return string The HTML-serialized form of the block
17
- */
18
- function serialize_block( $block ) {
19
- // Non-block content has no block name.
20
- if ( null === $block['blockName'] ) {
21
- return $block['innerHTML'];
22
- }
23
-
24
- $unwanted = array( '--', '<', '>', '&', '\"' );
25
- $wanted = array( '\u002d\u002d', '\u003c', '\u003e', '\u0026', '\u0022' );
26
-
27
- $name = 0 === strpos( $block['blockName'], 'core/' ) ? substr( $block['blockName'], 5 ) : $block['blockName'];
28
- $has_attrs = ! empty( $block['attrs'] );
29
- $attrs = $has_attrs ? str_replace( $unwanted, $wanted, wp_json_encode( $block['attrs'] ) ) : '';
30
-
31
- // Early abort for void blocks holding no content.
32
- if ( empty( $block['innerContent'] ) ) {
33
- return $has_attrs
34
- ? "<!-- wp:{$name} {$attrs} /-->"
35
- : "<!-- wp:{$name} /-->";
36
- }
37
-
38
- $output = $has_attrs
39
- ? "<!-- wp:{$name} {$attrs} -->\n"
40
- : "<!-- wp:{$name} -->\n";
41
-
42
- $inner_block_index = 0;
43
- foreach ( $block['innerContent'] as $chunk ) {
44
- $output .= null === $chunk
45
- ? serialize_block( $block['innerBlocks'][ $inner_block_index++ ] )
46
- : $chunk;
47
-
48
- $output .= "\n";
49
- }
50
-
51
- $output .= "<!-- /wp:{$name} -->";
52
-
53
- return $output;
54
- }
55
- }
56
-
57
- if ( ! function_exists( 'serialize_blocks' ) ) {
58
- /**
59
- * Renders an HTML-serialized form of a list of block objects
60
- * from https://core.trac.wordpress.org/ticket/47375
61
- *
62
- * Should be available since WordPress 5.3.0.
63
- *
64
- * @param array $blocks The list of parsed block objects.
65
- * @return string The HTML-serialized form of the list of blocks.
66
- */
67
- function serialize_blocks( $blocks ) {
68
- return implode( "\n\n", array_map( 'serialize_block', $blocks ) );
69
- }
70
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/templates/class-rest-templates-controller.php DELETED
@@ -1,49 +0,0 @@
1
- <?php
2
- /**
3
- * REST Templates Controller file.
4
- *
5
- * @package A8C\FSE
6
- */
7
-
8
- namespace A8C\FSE;
9
-
10
- /**
11
- * Based on `WP_REST_Blocks_Controller` from core
12
- */
13
- class REST_Templates_Controller extends \WP_REST_Posts_Controller {
14
-
15
- /**
16
- * Checks if a template can be read.
17
- *
18
- * @param object $post Post object that backs the template.
19
- * @return bool Whether the template can be read.
20
- */
21
- public function check_read_permission( $post ) {
22
- // Ensure that the user is logged in and has the edit_posts capability.
23
- $post_type = get_post_type_object( $post->post_type );
24
- if ( ! current_user_can( $post_type->cap->read_post, $post->ID ) ) {
25
- return false;
26
- }
27
-
28
- return parent::check_read_permission( $post );
29
- }
30
-
31
- /**
32
- * Retrieves the template's schema, conforming to JSON Schema.
33
- *
34
- * @return array Item schema data.
35
- */
36
- public function get_item_schema() {
37
- $schema = parent::get_item_schema();
38
-
39
- /*
40
- * Allow all contexts to access `title.raw` and `content.raw`. Clients always
41
- * need the raw markup of a reusable template to do anything useful, e.g. parse
42
- * it or display it in an editor.
43
- */
44
- $schema['properties']['title']['properties']['raw']['context'] = array( 'view', 'edit' );
45
- $schema['properties']['content']['properties']['raw']['context'] = array( 'view', 'edit' );
46
-
47
- return $schema;
48
- }
49
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/templates/class-template-image-inserter.php DELETED
@@ -1,174 +0,0 @@
1
- <?php
2
- /**
3
- * Full site editing file.
4
- *
5
- * @package A8C\FSE
6
- */
7
-
8
- namespace A8C\FSE;
9
-
10
- /**
11
- * Class Template_Image_Inserter
12
- */
13
- class Template_Image_Inserter {
14
- /**
15
- * Uploads specific images to the media libraray
16
- *
17
- * It then checks if any of the passed image URLs are also in the post content
18
- * of any of the passed post IDs. If so, then the post content is updated to
19
- * use the new local URL instead of the passed URL.
20
- *
21
- * @param array $img_urls URLs of images which should be uploaded.
22
- * @param array $post_ids An array of posts IDs which should be updated with newly uploaded image URLs.
23
- */
24
- public function copy_images_and_update_posts( $img_urls = [], $post_ids = [] ) {
25
- do_action(
26
- 'a8c_fse_log',
27
- 'template_image_sideload_begin',
28
- [
29
- 'context' => 'Template_Image_Inserter->copy_images_and_update_posts',
30
- 'image_urls' => $img_urls,
31
- ]
32
- );
33
-
34
- if ( empty( $img_urls ) || empty( $post_ids ) ) {
35
- return;
36
- }
37
-
38
- $images = $this->upload_images( $img_urls );
39
- foreach ( $post_ids as $id ) {
40
- $this->update_post_images( $id, $images );
41
- }
42
- }
43
-
44
- /**
45
- * Upload an array of images to the media library.
46
- *
47
- * If an file fails to upload, the error is logged to the FSE error handler.
48
- *
49
- * @param array $image_urls Images URLs to upload.
50
- * @return array Each entry contains the old and new URL of an image if successfully uploaded.
51
- */
52
- public function upload_images( $image_urls ) {
53
- return array_reduce(
54
- $image_urls,
55
- function( $accumulator, $url ) {
56
- // 1. Attempt to sideload the image and get the local URL.
57
- $local_url = $this->upload_image( $url );
58
-
59
- // 2. Check if anything went wrong during upload.
60
- $error_msg = null;
61
- if ( is_wp_error( $local_url ) ) {
62
- $error_msg = $local_url->get_error_message();
63
- } elseif ( ! is_string( $local_url ) ) {
64
- $error_msg = 'Issue uploading the image.';
65
- }
66
-
67
- // 3. If there was an error, report it.
68
- if ( is_string( $error_msg ) ) {
69
- do_action(
70
- 'a8c_fse_log',
71
- 'image_sideload_failure',
72
- [
73
- 'context' => 'Template_Image_Inserter->upload_images',
74
- 'error' => $error_msg,
75
- 'remote_image_url' => $url,
76
- ]
77
- );
78
- } else {
79
- // 4. Otherwise, save the url.
80
- $accumulator[] = [
81
- 'old_url' => $url,
82
- 'new_url' => $local_url,
83
- ];
84
- }
85
- return $accumulator;
86
- },
87
- []
88
- );
89
- }
90
-
91
- /**
92
- * Sideload a remote image URL and return the local attachment URL.
93
- *
94
- * @param string $image_url The URL to sideload to the local site.
95
- * @return string The local URL of the newly uploaded image.
96
- */
97
- public function upload_image( $image_url ) {
98
- if ( ! function_exists( 'media_handle_sideload' ) ) {
99
- require_once ABSPATH . '/wp-admin/includes/file.php';
100
- require_once ABSPATH . '/wp-admin/includes/media.php';
101
- require_once ABSPATH . '/wp-admin/includes/image.php';
102
- }
103
-
104
- // 1. Download the image.
105
- $local_file = download_url( $image_url );
106
- if ( is_wp_error( $local_file ) ) {
107
- return $local_file;
108
- }
109
-
110
- // 2. Create a file object.
111
- $file_name = basename( wp_parse_url( $image_url, PHP_URL_PATH ) );
112
- $desc = 'Template Part Image';
113
- $file_array = [
114
- 'name' => $file_name,
115
- 'tmp_name' => $local_file,
116
- ];
117
-
118
- // 3. Sideload, remove tmp file, and return the local URL.
119
- $id = media_handle_sideload( $file_array, 0, $desc );
120
- // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
121
- @unlink( $local_file );
122
-
123
- if ( is_wp_error( $id ) ) {
124
- return $id;
125
- }
126
-
127
- return wp_get_attachment_url( $id );
128
- }
129
-
130
- /**
131
- * Upload an image URL.
132
- *
133
- * @param array $post_id The post ID which should be updated with the new URLs.
134
- * @param array $images An array of old/new image URLs to replace.
135
- */
136
- public function update_post_images( $post_id, $images ) {
137
- $content = get_post_field( 'post_content', $post_id );
138
- if ( empty( $content ) ) {
139
- do_action(
140
- 'a8c_fse_log',
141
- 'update_post_with_new_images_get_post_failure',
142
- [
143
- 'context' => 'Template_Image_Inserter->update_post_images',
144
- 'error' => 'Could not retrieve post content.',
145
- 'post_id' => $post_id,
146
- ]
147
- );
148
- return;
149
- }
150
-
151
- // Replace the matching images in the content and update the post.
152
- foreach ( $images as $image ) {
153
- $content = str_replace( $image['old_url'], $image['new_url'], $content );
154
- }
155
- $res = wp_update_post(
156
- [
157
- 'ID' => $post_id,
158
- 'post_content' => $content,
159
- ]
160
- );
161
-
162
- if ( ! $res ) {
163
- do_action(
164
- 'a8c_fse_log',
165
- 'update_post_with_new_images_update_post_failure',
166
- [
167
- 'context' => 'Template_Image_Inserter->update_post_images',
168
- 'error' => 'Issue updating the post with the new image URLs.',
169
- 'image_urls' => $images,
170
- ]
171
- );
172
- }
173
- }
174
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/templates/class-wp-template-inserter.php DELETED
@@ -1,537 +0,0 @@
1
- <?php
2
- /**
3
- * Full site editing file.
4
- *
5
- * @package A8C\FSE
6
- */
7
-
8
- namespace A8C\FSE;
9
-
10
- /**
11
- * The strategy to use for loading the default template part content.
12
- *
13
- * @typedef {String="use-api","use-local"} LoadingStrategy
14
- */
15
-
16
- /**
17
- * Class WP_Template_Inserter
18
- */
19
- class WP_Template_Inserter {
20
- /**
21
- * Template header content.
22
- *
23
- * @var string $header_content
24
- */
25
- private $header_content;
26
-
27
- /**
28
- * Template footer content.
29
- *
30
- * @var string $footer_content
31
- */
32
- private $footer_content;
33
-
34
- /**
35
- * Current theme slug.
36
- *
37
- * @var string $theme_slug
38
- */
39
- private $theme_slug;
40
-
41
- /**
42
- * Image URLs contained in the returned from the template API
43
- *
44
- * @var array $image_urls
45
- */
46
- private $image_urls;
47
-
48
- /**
49
- * This site option will be used to indicate that template data has already been
50
- * inserted for this theme, in order to prevent this functionality from running
51
- * more than once.
52
- *
53
- * @var string $fse_template_data_option
54
- */
55
- private $fse_template_data_option;
56
-
57
- /**
58
- * This site option will be used to indicate that default page data has already been
59
- * inserted for this theme, in order to prevent this functionality from running
60
- * more than once.
61
- *
62
- * @var string $fse_page_data_option
63
- */
64
- private $fse_page_data_option = 'fse-page-data-v1';
65
-
66
- /**
67
- * The strategy to use for default data insertion.
68
- *
69
- * 'use-api' will use the wpcom API to get specifc content depending on the theme.
70
- *
71
- * 'use-local' will use the locally defined defaults.
72
- *
73
- * @var {LoadingStrategy} $loading_strategy
74
- */
75
- private $loading_strategy;
76
-
77
- /**
78
- * WP_Template_Inserter constructor.
79
- *
80
- * @param string $theme_slug Current theme slug.
81
- * @param {LoadingStrategy} $loading_strategy The strategy to use to load the template part content.
82
- */
83
- public function __construct( $theme_slug, $loading_strategy = 'use-api' ) {
84
- $this->theme_slug = $theme_slug;
85
- $this->header_content = '';
86
- $this->footer_content = '';
87
- $this->loading_strategy = $loading_strategy;
88
-
89
- /*
90
- * Previously the option suffix was '-fse-template-data'. Bumping this to '-fse-template-data-v1'
91
- * to differentiate it from the old data that was not provided by the API. Note that we don't want
92
- * to tie this to plugin version constant, because that would trigger the insertion on each plugin
93
- * update, even when it's not necessary (it would duplicate existing data).
94
- */
95
- $this->fse_template_data_option = $this->theme_slug . '-fse-template-data-v1';
96
- }
97
-
98
-
99
- /**
100
- * Retrieves template parts content.
101
- */
102
- public function fetch_template_parts() {
103
- // Use default data if we don't want to fetch from the API.
104
- if ( 'use-local' === $this->loading_strategy ) {
105
- $this->header_content = $this->get_default_header();
106
- $this->footer_content = $this->get_default_footer();
107
- return;
108
- }
109
-
110
- $request_url = 'https://public-api.wordpress.com/wpcom/v2/full-site-editing/templates';
111
-
112
- $request_args = [
113
- 'body' => [ 'theme_slug' => $this->theme_slug ],
114
- ];
115
-
116
- $response = $this->fetch_retry( $request_url, $request_args );
117
-
118
- if ( ! $response ) {
119
- do_action(
120
- 'a8c_fse_log',
121
- 'template_population_failure',
122
- [
123
- 'context' => 'WP_Template_Inserter->fetch_template_parts',
124
- 'error' => 'Fetch retry timeout',
125
- 'theme_slug' => $this->theme_slug,
126
- ]
127
- );
128
- $this->header_content = $this->get_default_header();
129
- $this->footer_content = $this->get_default_footer();
130
- return;
131
- }
132
-
133
- $api_response = json_decode( wp_remote_retrieve_body( $response ), true );
134
- if ( ! empty( $api_response['code'] ) && 'not_found' === $api_response['code'] ) {
135
- do_action(
136
- 'a8c_fse_log',
137
- 'template_population_failure',
138
- [
139
- 'context' => 'WP_Template_Inserter->fetch_template_parts',
140
- 'error' => 'Did not find remote template data for the given theme.',
141
- 'theme_slug' => $this->theme_slug,
142
- ]
143
- );
144
- return;
145
- }
146
-
147
- // Default to first returned header for now. Support for multiple headers will be added in future iterations.
148
- if ( ! empty( $api_response['headers'] ) ) {
149
- $this->header_content = $api_response['headers'][0];
150
- }
151
-
152
- // Default to first returned footer for now. Support for multiple footers will be added in future iterations.
153
- if ( ! empty( $api_response['footers'] ) ) {
154
- $this->footer_content = $api_response['footers'][0];
155
- }
156
-
157
- // This should contain all image URLs for images in any header or footer.
158
- if ( ! empty( $api_response['image_urls'] ) ) {
159
- $this->image_urls = $api_response['image_urls'];
160
- }
161
- }
162
-
163
- /**
164
- * Retries a call to wp_remote_get on error.
165
- *
166
- * @param string $request_url Url of the api call to make.
167
- * @param string $request_args Addtional arguments for the api call.
168
- * @param int $attempt The number of the attempt being made.
169
- * @return array wp_remote_get reponse array
170
- */
171
- private function fetch_retry( $request_url, $request_args = null, $attempt = 1 ) {
172
- $max_retries = 3;
173
-
174
- $response = wp_remote_get( $request_url, $request_args );
175
-
176
- if ( ! is_wp_error( $response ) ) {
177
- return $response;
178
- }
179
-
180
- if ( $attempt > $max_retries ) {
181
- return;
182
- }
183
-
184
- sleep( pow( 2, $attempt ) );
185
- $attempt++;
186
- $this->fetch_retry( $request_url, $request_args, $attempt );
187
- }
188
-
189
- /**
190
- * Returns a default header if call to template api fails for some reason.
191
- *
192
- * @return string Content of a default header
193
- */
194
- public function get_default_header() {
195
- return '<!-- wp:a8c/site-description /-->
196
- <!-- wp:a8c/site-title /-->
197
- <!-- wp:a8c/navigation-menu /-->';
198
- }
199
-
200
- /**
201
- * Returns a default footer if call to template api fails for some reason.
202
- *
203
- * @return string Content of a default footer
204
- */
205
- public function get_default_footer() {
206
- return '<!-- wp:a8c/navigation-menu /-->';
207
- }
208
-
209
- /**
210
- * Determines whether FSE data has already been inserted.
211
- *
212
- * @return bool True if FSE data has already been inserted, false otherwise.
213
- */
214
- public function is_template_data_inserted() {
215
- return get_option( $this->fse_template_data_option ) ? true : false;
216
- }
217
-
218
- /**
219
- * This function will be called on plugin activation hook.
220
- */
221
- public function insert_default_template_data() {
222
- do_action(
223
- 'a8c_fse_log',
224
- 'before_template_population',
225
- [
226
- 'context' => 'WP_Template_Inserter->insert_default_template_data',
227
- 'theme_slug' => $this->theme_slug,
228
- ]
229
- );
230
-
231
- if ( $this->is_template_data_inserted() ) {
232
- /*
233
- * Bail here to prevent inserting the FSE data twice for any given theme.
234
- * Multiple themes will still be able to insert different templates.
235
- */
236
- do_action(
237
- 'a8c_fse_log',
238
- 'template_population_failure',
239
- [
240
- 'context' => 'WP_Template_Inserter->insert_default_template_data',
241
- 'error' => 'Data already exist',
242
- 'theme_slug' => $this->theme_slug,
243
- ]
244
- );
245
- return;
246
- }
247
-
248
- // Set header and footer content based on data fetched from the WP.com API.
249
- $this->fetch_template_parts();
250
-
251
- // Avoid creating template parts if data hasn't been fetched properly.
252
- if ( empty( $this->header_content ) || empty( $this->footer_content ) ) {
253
- return;
254
- }
255
-
256
- $this->register_template_post_types();
257
-
258
- $header_id = wp_insert_post(
259
- [
260
- 'post_title' => 'Header',
261
- 'post_content' => $this->header_content,
262
- 'post_status' => 'publish',
263
- 'post_type' => 'wp_template_part',
264
- 'comment_status' => 'closed',
265
- 'ping_status' => 'closed',
266
- ]
267
- );
268
-
269
- if ( ! term_exists( "$this->theme_slug-header", 'wp_template_part_type' ) ) {
270
- wp_insert_term( "$this->theme_slug-header", 'wp_template_part_type' );
271
- }
272
-
273
- wp_set_object_terms( $header_id, "$this->theme_slug-header", 'wp_template_part_type' );
274
-
275
- $footer_id = wp_insert_post(
276
- [
277
- 'post_title' => 'Footer',
278
- 'post_content' => $this->footer_content,
279
- 'post_status' => 'publish',
280
- 'post_type' => 'wp_template_part',
281
- 'comment_status' => 'closed',
282
- 'ping_status' => 'closed',
283
- ]
284
- );
285
-
286
- if ( ! term_exists( "$this->theme_slug-footer", 'wp_template_part_type' ) ) {
287
- wp_insert_term( "$this->theme_slug-footer", 'wp_template_part_type' );
288
- }
289
-
290
- wp_set_object_terms( $footer_id, "$this->theme_slug-footer", 'wp_template_part_type' );
291
-
292
- add_option( $this->fse_template_data_option, true );
293
-
294
- // Note: we set the option before doing the image upload because the template
295
- // parts can work with the remote URLs even if this fails.
296
- $image_urls = $this->image_urls;
297
- if ( ! empty( $image_urls ) ) {
298
- // Uploading images locally does not work in the WordPress.com environment,
299
- // so we use an action to handle it with Headstart there.
300
- if ( has_action( 'a8c_fse_upload_template_part_images' ) ) {
301
- do_action( 'a8c_fse_upload_template_part_images', $image_urls, [ $header_id, $footer_id ] );
302
- } else {
303
- $image_inserter = new Template_Image_Inserter();
304
- $image_inserter->copy_images_and_update_posts( $image_urls, [ $header_id, $footer_id ] );
305
- }
306
- }
307
-
308
- do_action(
309
- 'a8c_fse_log',
310
- 'template_population_success',
311
- [
312
- 'context' => 'WP_Template_Inserter->insert_default_template_data',
313
- 'theme_slug' => $this->theme_slug,
314
- ]
315
- );
316
- }
317
-
318
- /**
319
- * Determines whether default pages have already been created.
320
- *
321
- * @return bool True if default pages have already been created, false otherwise.
322
- */
323
- public function is_pages_data_inserted() {
324
- return get_option( $this->fse_page_data_option ) ? true : false;
325
- }
326
-
327
- /**
328
- * Inserts default About and Contact pages based on Starter Page Templates content.
329
- *
330
- * The insertion will not happen if this data has been already inserted or if pages
331
- * with 'About' and 'Contact' titles already exist.
332
- */
333
- public function insert_default_pages() {
334
- do_action(
335
- 'a8c_fse_log',
336
- 'before_pages_population',
337
- [
338
- 'context' => 'WP_Template_Inserter->insert_default_pages',
339
- 'theme_slug' => $this->theme_slug,
340
- ]
341
- );
342
-
343
- // Bail if this data has already been inserted.
344
- if ( $this->is_pages_data_inserted() ) {
345
- do_action(
346
- 'a8c_fse_log',
347
- 'pages_population_failure',
348
- [
349
- 'context' => 'WP_Template_Inserter->insert_default_pages',
350
- 'error' => 'Data already exist',
351
- 'theme_slug' => $this->theme_slug,
352
- ]
353
- );
354
- return;
355
- }
356
-
357
- $request_url = add_query_arg(
358
- [
359
- '_locale' => $this->get_iso_639_locale(),
360
- ],
361
- 'https://public-api.wordpress.com/wpcom/v2/verticals/m1/templates'
362
- );
363
-
364
- $response = $this->fetch_retry( $request_url );
365
-
366
- if ( ! $response ) {
367
- do_action(
368
- 'a8c_fse_log',
369
- 'pages_population_failure',
370
- [
371
- 'context' => 'WP_Template_Inserter->insert_default_pages',
372
- 'error' => 'Fetch retry timeout',
373
- 'theme_slug' => $this->theme_slug,
374
- ]
375
- );
376
- return;
377
- }
378
-
379
- $api_response = json_decode( wp_remote_retrieve_body( $response ), true );
380
-
381
- // Convert templates response to [ slug => content ] pairs to extract required content more easily.
382
- $template_content_by_slug = wp_list_pluck( $api_response['templates'], 'content', 'slug' );
383
-
384
- if ( empty( get_page_by_title( 'About' ) ) && ! empty( $template_content_by_slug['about'] ) ) {
385
- wp_insert_post(
386
- [
387
- 'post_title' => _x( 'About', 'Default page title', 'full-site-editing' ),
388
- 'post_content' => $template_content_by_slug['about'],
389
- 'post_status' => 'publish',
390
- 'post_type' => 'page',
391
- 'menu_order' => 1,
392
- ]
393
- );
394
- }
395
-
396
- if ( empty( get_page_by_title( 'Contact' ) ) && ! empty( $template_content_by_slug['contact'] ) ) {
397
- wp_insert_post(
398
- [
399
- 'post_title' => _x( 'Contact', 'Default page title', 'full-site-editing' ),
400
- 'post_content' => $template_content_by_slug['contact'],
401
- 'post_status' => 'publish',
402
- 'post_type' => 'page',
403
- 'menu_order' => 1,
404
- ]
405
- );
406
- }
407
-
408
- update_option( $this->fse_page_data_option, true );
409
-
410
- do_action(
411
- 'a8c_fse_log',
412
- 'pages_population_success',
413
- [
414
- 'context' => 'WP_Template_Inserter->insert_default_pages',
415
- 'theme_slug' => $this->theme_slug,
416
- ]
417
- );
418
- }
419
-
420
- /**
421
- * Returns ISO 639 conforming locale string.
422
- *
423
- * @return string ISO 639 locale string
424
- */
425
- public function get_iso_639_locale() {
426
- $language = strtolower( get_locale() );
427
-
428
- if ( in_array( $language, [ 'zh_tw', 'zh-tw', 'zh_cn', 'zh-cn' ], true ) ) {
429
- $language = str_replace( '_', '-', $language );
430
- } else {
431
- $language = preg_replace( '/([-_].*)$/i', '', $language );
432
- }
433
-
434
- return $language;
435
- }
436
-
437
- /**
438
- * Register post types.
439
- */
440
- public function register_template_post_types() {
441
- register_post_type(
442
- 'wp_template_part',
443
- array(
444
- 'labels' => array(
445
- 'name' => _x( 'Template Parts', 'post type general name', 'full-site-editing' ),
446
- 'singular_name' => _x( 'Template Part', 'post type singular name', 'full-site-editing' ),
447
- 'menu_name' => _x( 'Template Parts', 'admin menu', 'full-site-editing' ),
448
- 'name_admin_bar' => _x( 'Template Part', 'add new on admin bar', 'full-site-editing' ),
449
- 'add_new' => _x( 'Add New', 'Template', 'full-site-editing' ),
450
- 'add_new_item' => __( 'Add New Template Part', 'full-site-editing' ),
451
- 'new_item' => __( 'New Template Part', 'full-site-editing' ),
452
- 'edit_item' => __( 'Edit Template Part', 'full-site-editing' ),
453
- 'view_item' => __( 'View Template Part', 'full-site-editing' ),
454
- 'all_items' => __( 'All Template Parts', 'full-site-editing' ),
455
- 'search_items' => __( 'Search Template Parts', 'full-site-editing' ),
456
- 'not_found' => __( 'No template parts found.', 'full-site-editing' ),
457
- 'not_found_in_trash' => __( 'No template parts found in Trash.', 'full-site-editing' ),
458
- 'filter_items_list' => __( 'Filter template parts list', 'full-site-editing' ),
459
- 'items_list_navigation' => __( 'Template parts list navigation', 'full-site-editing' ),
460
- 'items_list' => __( 'Template parts list', 'full-site-editing' ),
461
- 'item_published' => __( 'Template part published.', 'full-site-editing' ),
462
- 'item_published_privately' => __( 'Template part published privately.', 'full-site-editing' ),
463
- 'item_reverted_to_draft' => __( 'Template part reverted to draft.', 'full-site-editing' ),
464
- 'item_scheduled' => __( 'Template part scheduled.', 'full-site-editing' ),
465
- 'item_updated' => __( 'Template part updated.', 'full-site-editing' ),
466
- ),
467
- 'menu_icon' => 'dashicons-layout',
468
- 'public' => false,
469
- 'show_ui' => true, // Otherwise we'd get permission error when trying to edit them.
470
- 'show_in_menu' => false,
471
- 'rewrite' => false,
472
- 'show_in_rest' => true, // Otherwise previews won't be generated in full page view.
473
- 'rest_base' => 'template_parts',
474
- 'rest_controller_class' => __NAMESPACE__ . '\REST_Templates_Controller',
475
- 'capability_type' => 'template_part',
476
- 'capabilities' => array(
477
- // You need to be able to edit posts, in order to read templates in their raw form.
478
- 'read' => 'edit_posts',
479
- // You need to be able to customize, in order to create templates.
480
- 'create_posts' => 'edit_theme_options',
481
- 'edit_posts' => 'edit_theme_options',
482
- 'delete_posts' => 'edit_theme_options',
483
- 'edit_published_posts' => 'edit_theme_options',
484
- 'delete_published_posts' => 'edit_theme_options',
485
- 'edit_others_posts' => 'edit_theme_options',
486
- 'delete_others_posts' => 'edit_theme_options',
487
- 'publish_posts' => 'edit_theme_options',
488
- ),
489
- 'map_meta_cap' => true,
490
- 'supports' => array(
491
- 'title',
492
- 'editor',
493
- 'revisions',
494
- ),
495
- )
496
- );
497
-
498
- register_taxonomy(
499
- 'wp_template_part_type',
500
- 'wp_template_part',
501
- array(
502
- 'labels' => array(
503
- 'name' => _x( 'Template Part Types', 'taxonomy general name', 'full-site-editing' ),
504
- 'singular_name' => _x( 'Template Part Type', 'taxonomy singular name', 'full-site-editing' ),
505
- 'menu_name' => _x( 'Template Part Types', 'admin menu', 'full-site-editing' ),
506
- 'all_items' => __( 'All Template Part Types', 'full-site-editing' ),
507
- 'edit_item' => __( 'Edit Template Part Type', 'full-site-editing' ),
508
- 'view_item' => __( 'View Template Part Type', 'full-site-editing' ),
509
- 'update_item' => __( 'Update Template Part Type', 'full-site-editing' ),
510
- 'add_new_item' => __( 'Add New Template Part Type', 'full-site-editing' ),
511
- 'new_item_name' => __( 'New Template Part Type', 'full-site-editing' ),
512
- 'parent_item' => __( 'Parent Template Part Type', 'full-site-editing' ),
513
- 'parent_item_colon' => __( 'Parent Template Part Type:', 'full-site-editing' ),
514
- 'search_items' => __( 'Search Template Part Types', 'full-site-editing' ),
515
- 'not_found' => __( 'No template part types found.', 'full-site-editing' ),
516
- 'back_to_items' => __( 'Back to template part types', 'full-site-editing' ),
517
- ),
518
- 'public' => false,
519
- 'publicly_queryable' => false,
520
- 'show_ui' => false,
521
- 'show_in_menu' => false,
522
- 'show_in_nav_menu' => false,
523
- 'show_in_rest' => true,
524
- 'rest_base' => 'template_part_types',
525
- 'show_tagcloud' => false,
526
- 'hierarchical' => true,
527
- 'rewrite' => false,
528
- 'capabilities' => array(
529
- 'manage_terms' => 'edit_theme_options',
530
- 'edit_terms' => 'edit_theme_options',
531
- 'delete_terms' => 'edit_theme_options',
532
- 'assign_terms' => 'edit_theme_options',
533
- ),
534
- )
535
- );
536
- }
537
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/full-site-editing/templates/class-wp-template.php DELETED
@@ -1,204 +0,0 @@
1
- <?php
2
- /**
3
- * WP Template file.
4
- *
5
- * @package A8C\FSE
6
- */
7
-
8
- namespace A8C\FSE;
9
-
10
- /**
11
- * Class WP_Template
12
- */
13
- class WP_Template {
14
- /**
15
- * Header template type constant.
16
- *
17
- * @var string HEADER
18
- */
19
- const HEADER = 'header';
20
-
21
- /**
22
- * Footer template type constant
23
- *
24
- * @var string FOOTER
25
- */
26
- const FOOTER = 'footer';
27
-
28
- /**
29
- * Name of the currently active theme that is used to reference its template CPTs.
30
- *
31
- * @var string $current_theme_name Name of currently active theme on the site.
32
- */
33
- private $current_theme_name;
34
-
35
- /**
36
- * List of template types that FSE is currently supporting.
37
- *
38
- * @var array $supported_template_types Array of strings containing supported template types.
39
- */
40
- public $supported_template_types = [ self::HEADER, self::FOOTER ];
41
-
42
- /**
43
- * A8C_WP_Template constructor.
44
- *
45
- * @param string $theme Defaults to the current theme slug, but can be
46
- * overriden to use this class with themes which are
47
- * not currently active.
48
- */
49
- public function __construct( $theme = null ) {
50
- if ( ! isset( $theme ) ) {
51
- $theme = get_stylesheet();
52
- }
53
- $this->current_theme_name = normalize_theme_slug( $theme );
54
- }
55
-
56
- /**
57
- * Checks whether the provided template type is supported in FSE.
58
- *
59
- * @param string $template_type String representing the template type.
60
- *
61
- * @return bool True if provided template type is supported in FSE, false otherwise.
62
- */
63
- public function is_supported_template_type( $template_type ) {
64
- return in_array( $template_type, $this->supported_template_types, true );
65
- }
66
-
67
- /**
68
- * Returns the post ID of the default template CPT for a given template type.
69
- *
70
- * @param string $template_type String representing the template type.
71
- *
72
- * @return null|int Template ID if it exists or null otherwise.
73
- */
74
- public function get_template_id( $template_type ) {
75
- if ( ! $this->is_supported_template_type( $template_type ) ) {
76
- return null;
77
- }
78
-
79
- $term = get_term_by( 'name', "$this->current_theme_name-$template_type", 'wp_template_part_type', ARRAY_A );
80
-
81
- // Bail if current site doesn't have this term registered.
82
- if ( ! isset( $term['term_id'] ) ) {
83
- return null;
84
- }
85
-
86
- $template_ids = get_objects_in_term( $term['term_id'], $term['taxonomy'], [ 'order' => 'DESC' ] );
87
-
88
- // Bail if we haven't found any post instances for this template type.
89
- if ( empty( $template_ids ) ) {
90
- return null;
91
- }
92
-
93
- /*
94
- * Assuming that we'll have just one default template for now.
95
- * We'll add support for multiple header and footer variations in future iterations.
96
- */
97
- return $template_ids[0];
98
- }
99
-
100
- /**
101
- * Returns template content for given template type.
102
- *
103
- * @param string $template_type String representing the template type.
104
- *
105
- * @return null|string Template content if it exists or null otherwise.
106
- */
107
- public function get_template_content( $template_type ) {
108
- if ( ! $this->is_supported_template_type( $template_type ) ) {
109
- return null;
110
- }
111
-
112
- $template_id = $this->get_template_id( $template_type );
113
-
114
- if ( null === $template_id ) {
115
- return null;
116
- }
117
-
118
- $template_post = get_post( $template_id );
119
-
120
- if ( null === $template_post ) {
121
- return;
122
- }
123
-
124
- return $template_post->post_content;
125
- }
126
-
127
- /**
128
- * Returns full page template content.
129
- *
130
- * We only support one page template for now with header at the top and footer at the bottom.
131
- *
132
- * @return null|string
133
- */
134
- public function get_page_template_content() {
135
- $header_id = $this->get_template_id( self::HEADER );
136
- $footer_id = $this->get_template_id( self::FOOTER );
137
-
138
- /*
139
- * Bail if we are missing header or footer. Otherwise this would cause us to
140
- * always return some page template content and show template parts (with empty IDs),
141
- * even for themes that don't support FSE.
142
- */
143
- if ( ! $header_id || ! $footer_id ) {
144
- return null;
145
- }
146
-
147
- return "<!-- wp:a8c/template {\"templateId\":$header_id,\"label\":\"" . __( 'Header', 'full-site-editing' ) . '","className":"fse-template-part fse-header"} /-->' .
148
- '<!-- wp:a8c/post-content /-->' .
149
- "<!-- wp:a8c/template {\"templateId\":$footer_id,\"label\":\"" . __( 'Footer', 'full-site-editing' ) . '","className":"fse-template-part fse-footer"} /-->';
150
- }
151
-
152
- /**
153
- * Returns array of blocks that represent the template.
154
- *
155
- * @return array
156
- */
157
- public function get_template_blocks() {
158
- $template_content = $this->get_page_template_content();
159
- $template_blocks = parse_blocks( $template_content );
160
- return is_array( $template_blocks ) ? $template_blocks : [];
161
- }
162
-
163
- /**
164
- * Output FSE template markup.
165
- *
166
- * @param string $template_type String representing the template type.
167
- *
168
- * @return null|void Null if unsupported template type is passed, outputs content otherwise.
169
- */
170
- public function output_template_content( $template_type ) {
171
- if ( ! $this->is_supported_template_type( $template_type ) ) {
172
- return null;
173
- }
174
-
175
- // Things that follow are from wp-includes/default-filters.php
176
- // not everything is appropriate for template content as opposed to post content.
177
- global $wp_embed;
178
- $content = $this->get_template_content( $template_type );
179
-
180
- // 8 priority
181
- $content = $wp_embed->run_shortcode( $content );
182
- $content = $wp_embed->autoembed( $content );
183
-
184
- // 9 priority
185
- $content = do_blocks( $content );
186
-
187
- // 10 priority
188
- $content = wptexturize( $content );
189
-
190
- // 11 priority
191
- $content = do_shortcode( $content );
192
-
193
- $content = prepend_attachment( $content );
194
-
195
- if ( has_filter( 'a8c_fse_make_content_images_responsive' ) ) {
196
- $content = apply_filters( 'a8c_fse_make_content_images_responsive', $content );
197
- } else {
198
- $content = wp_make_content_images_responsive( $content );
199
- }
200
-
201
- // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped
202
- echo $content;
203
- }
204
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/global-styles/README-DATA.md DELETED
@@ -1,363 +0,0 @@
1
- # Global Styles approach to Data <!-- omit in toc -->
2
-
3
- Global Styles adds a new JSON REST API endpoint. It is a thin endpoint that outsources the data processing to the `\Automattic\Jetpack\Global_Styles\Data_Set` class, which implements a declarative approach to data retrieval and persistance.
4
-
5
- In this document we'll go through the existing API:
6
-
7
- - [Introduction](#introduction)
8
- - [Literal Data Points](#literal-data-points)
9
- - [Option Data Points](#option-data-points)
10
- - [Fallback Values](#fallback-values)
11
- - [Working with option's properties](#working-with-options-properties)
12
- - [Updatable Options](#updatable-options)
13
- - [Filters to prepare and sanitize data](#filters-to-prepare-and-sanitize-data)
14
- - [Theme Data Points](#theme-data-points)
15
- - [Fallback Values](#fallback-values-1)
16
- - [Working with theme's properties](#working-with-themes-properties)
17
-
18
- ## Introduction
19
-
20
- The `\Automattic\Jetpack\Global_Styles\Data_Set` takes as input a declarative data format and knows how to process three kinds of data:
21
-
22
- ```php
23
- // Initialize
24
- $data_set = new \Automattic\Jetpack\Global_Styles\Data_Set( [
25
- 'font_list' => [
26
- 'type' => 'literal',
27
- 'default' => [
28
- 'Arvo',
29
- 'Libre Baskerville',
30
- 'Ubuntu',
31
- ],
32
- ],
33
- 'font_base_default' => [
34
- 'type' => 'theme',
35
- 'name' => [ 'jetpack-global-styles', 'font_base' ],
36
- 'default' => 'Ubuntu',
37
- ],
38
- 'site_name' => [
39
- 'type' => 'option',
40
- 'name' => 'blogname',
41
- 'default' => 'Your site name',
42
- ],
43
- ] );
44
-
45
- $data_set->get_data(); // Outputs data.
46
- $data_set->save_data( $new_data ); // Updates data.
47
- ```
48
-
49
- - **literal data points** are literal PHP values. These don't change over time and aren't saved to the database.
50
- - **options data points** are values that come from the WordPress Options API. These can also be updated.
51
- - **theme support data points** are values that come from the theme via `add_theme_support`.
52
-
53
- ## Literal Data Points
54
-
55
- Data points are considered to be of the *literal* kind if their `type` property value is `literal`. Their output is the literal PHP value in the `default` property, or `null` if none is provided.
56
-
57
- For this **input**:
58
-
59
- ```php
60
- $data_set = new \Automattic\Jetpack\Global_Styles\Data_Set( [
61
- 'font_base_default' => [
62
- 'type' => 'literal',
63
- 'default' => 'Libre Baskerville',
64
- ],
65
- 'font_headings_default' => [
66
- 'type' => 'literal',
67
- 'default' => 'Lora',
68
- ],
69
- ] );
70
- ```
71
-
72
- The **output** of `$data_set->get_data()` will be:
73
-
74
- ```php
75
- [
76
- 'font_base_default' => 'Libre Baskerville',
77
- 'font_headings_default' => 'Lora',
78
- ]
79
- ```
80
-
81
- Note that the `default` property can contain any valid PHP data.
82
-
83
- For example, use an array as **input**:
84
-
85
- ```php
86
- $data_set = new \Automattic\Jetpack\Global_Styles\Data_Set( [
87
- 'font_options' => [
88
- 'type' => 'literal',
89
- 'default' => [
90
- [
91
- 'label' => 'Ubuntu Font',
92
- 'value' => 'Ubuntu',
93
- ],
94
- 'Libre Baskerville',
95
- 'Lora',
96
- ],
97
- ],
98
- ] );
99
- ```
100
-
101
- The **output** of `$data_set->get_data()` will be:
102
-
103
- ```php
104
- [
105
- 'font_options' => [
106
- 0 => [
107
- 'label' => 'Ubuntu Font',
108
- 'value' => 'Ubuntu',
109
- ],
110
- 1 => 'Libre Baskerville'
111
- 2 => 'Lora',
112
- ]
113
- ]
114
- ```
115
-
116
- ## Option Data Points
117
-
118
- Data points are considered to be of the *option* kind if the value of the `type` property is `option`. These are the only data points that can be updated.
119
-
120
- The simplest use case is to operate with the contents of an option without further processing. This **input** can be expressed as:
121
-
122
- ```php
123
- $data_set = new \Automattic\Jetpack\Global_Styles\Data_Set( [
124
- 'site_name' => [
125
- 'type' => 'option',
126
- 'name' => 'blogname',
127
- ]
128
- ] );
129
- ```
130
-
131
- The result of `$data_set->get_data()` will **output** the value of the `blogname` option in the database, or `false` if it doesn't exists or does not have a value:
132
-
133
- ```php
134
- [
135
- 'site_name' => 'A WordPress Site'
136
- ]
137
- ```
138
-
139
- ### Fallback Values
140
-
141
- If the option does not exist or does not have a value, then the return value will be `false`, which replicates the WordPress Options API default behavior. In case you want to provide a fallback value, you can do so by using the `default` property.
142
-
143
- **Input**:
144
-
145
- ```php
146
- $data_set = new \Automattic\Jetpack\Global_Styles\Data_Set( [
147
- 'site_name' => [
148
- 'type' => 'option',
149
- 'name' => 'some_non_existing_option',
150
- 'default' => 'My cool site name',
151
- ]
152
- ] );
153
- ```
154
-
155
- **Output** if option doesn't exist:
156
-
157
- ```php
158
- [
159
- 'site_name' => 'My cool site name'
160
- ]
161
- ```
162
-
163
- ### Working with option's properties
164
-
165
- So far, we've exposed the whole option value. However, sometimes we want to unwrap an option and work with one of its properties instead.
166
-
167
- For example, let's say that there is an option called `jetpack_global_styles` whose value is an object such as:
168
-
169
- ```php
170
- [
171
- 'font_base' => 'Roboto',
172
- 'font_headings' => 'Playfair Display',
173
- ]
174
- ```
175
-
176
- For this **input**:
177
- ```php
178
- $data_set = new \Automattic\Jetpack\Global_Styles\Data_Set( [
179
- 'font_base' => [
180
- 'type' => 'option',
181
- 'name' => [ 'jetpack_global_styles', 'font_base' ],
182
- ]
183
- ] );
184
- ```
185
-
186
- The **output** of `$data_set->get_data()` will be:
187
-
188
- ```php
189
- [
190
- 'font_base' => 'Roboto',
191
- ]
192
- ```
193
-
194
- ### Updatable Options
195
-
196
- By default, options can't be updated and they won't be processed during the `$data_set->save_data( $new_data )` execution. For example, for this **input**:
197
-
198
- ```php
199
- $data_set = new \Automattic\Jetpack\Global_Styles\Data_Set( [
200
- 'site_name' => [
201
- 'type' => 'option',
202
- 'name' => 'blogname',
203
- ],
204
- ] );
205
- $data_set->save_data(
206
- [
207
- 'site_name' => 'A new site name'
208
- ]
209
- );
210
- ```
211
-
212
- By default, the `blogname` option value **won't be processed** so the new value will be discarded.
213
-
214
- Sometimes, though, we do want to update options. This can done by using the `updatable` key. Following the example above we set the option as updatable:
215
-
216
- ```php
217
- $data_set = new \Automattic\Jetpack\Global_Styles\Data_Set( [
218
- 'site_name' => [
219
- 'type' => 'option',
220
- 'name' => 'blogname',
221
- 'updatable' => true,
222
- ],
223
- ] );
224
- $data_set->save_data(
225
- [
226
- 'site_name' => 'A new site name.'
227
- ]
228
- );
229
- ```
230
-
231
- In this case, the `blogname` will be updated with the new value.
232
-
233
- If we were working with specific properties of the option instead:
234
-
235
- ```php
236
- $data_set = new \Automattic\Jetpack\Global_Styles\Data_Set( [
237
- 'font_base' => [
238
- 'type' => 'option',
239
- 'name' => [ 'jetpack_global_styles', 'font_base' ],
240
- 'updatable' => true,
241
- ],
242
- ] );
243
- $data_set->save_data(
244
- [
245
- 'font_base' => 'Domine'
246
- ]
247
- );
248
- ```
249
-
250
- The result will be that the `jetpack_global_styles` option will have its `font_base` property updated, while the rest will keep the same values.
251
-
252
- ### Filters to prepare and sanitize data
253
-
254
- **The `\Automattic\Jetpack\Global_Styles\Data_Set` doesn't do any validation or sanitization**, it's the consumer responsibility to do so. There are two filters that can be used to prepare, filter, validate and sanitize your data:
255
-
256
- - `jetpack_global_styles_data_set_get_data`: it runs as the last step of `get_data()` and receives the result of processing the data points, so plugins have the opportunity to further processing it to their needs before it's used anywhere else.
257
- - `jetpack_global_styles_data_set_save_data`: it runs as the first step of `save_data( $new_data )`, so plugins have the opportunity to validate and sanitize the incoming data to their needs before it's saved to the database.
258
-
259
- ## Theme Data Points
260
-
261
- Data points are considered to be of the *theme* kind if the property `type`'s value is `theme`.
262
-
263
- **Input** being:
264
-
265
- ```php
266
- $data_set = new \Automattic\Jetpack\Global_Styles\Data_Set( [
267
- 'jetpack_global_styles' => [
268
- 'type' => 'theme',
269
- 'name' => 'jetpack-global-styles',
270
- ],
271
- ] );
272
- ```
273
-
274
- This will pull data added via `add_theme_support` as in:
275
-
276
- ```php
277
- add_theme_support(
278
- 'jetpack-global-styles'
279
- [
280
- 'font_headings' => 'Ubuntu',
281
- ]
282
- );
283
- ```
284
-
285
- The **output** of `$data_set->get_data()` will be the value taken from theme support, or `null` if none was provided or the feature and/or property don't exist:
286
-
287
- ```php
288
- [
289
- 'jetpack_global_styles' => [
290
- 'font_headings' => 'Ubuntu',
291
- ],
292
- ]
293
- ```
294
-
295
- ### Fallback Values
296
-
297
- If the theme has declared support for a feature but hasn't provided any value, the output for that data point be `null`. In case you want to provide a fallback value, you can do so by using the `default` property.
298
-
299
- **Input**:
300
-
301
- ```php
302
- $data_set = new \Automattic\Jetpack\Global_Styles\Data_Set( [
303
- 'jetpack_global_styles' => [
304
- 'type' => 'theme',
305
- 'name' => 'jetpack-global-styles',
306
- 'default' => [
307
- 'font_headings' => 'Lora',
308
- ],
309
- ],
310
- ] );
311
- ```
312
-
313
- Being the `add_theme_support` declaration:
314
-
315
- ```php
316
- add_theme_support( 'jetpack-global-styles' );
317
- ```
318
-
319
- The **output** of `$data_set->get_data()` will be:
320
-
321
- ```php
322
- [
323
- 'jetpack_global_styles' =>[
324
- 'font_headings' => 'Lora',
325
- ]
326
- ]
327
- ```
328
-
329
- ## Working with theme's properties
330
-
331
- It is also possible to work with specific properties, unwrapping the theme support data.
332
-
333
- **Input**:
334
-
335
- ```php
336
- $data_set = new \Automattic\Jetpack\Global_Styles\Data_Set( [
337
- 'font_headings' => [
338
- 'type' => 'theme',
339
- 'name' => [ 'jetpack-global-styles', 'font_headings' ],
340
- ],
341
- ] );
342
- ```
343
-
344
- Being the `add_theme_support` declaration:
345
-
346
- ```php
347
- add_theme_support(
348
- 'jetpack-global-styles',
349
- [
350
- 'font_base' => 'Chivo',
351
- 'font_headings' => 'Ubuntu',
352
- ]
353
- );
354
-
355
- ```
356
-
357
- The **output** of `$data_set->get_data()` will be:
358
-
359
- ```php
360
- [
361
- 'font_headings' => 'Ubuntu',
362
- ]
363
- ```
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/global-styles/README.md DELETED
@@ -1,230 +0,0 @@
1
- # Global Styles plugin <!-- omit in toc -->
2
-
3
- This plugin creates a new sidebar for the block editor through which the users can update the styles site-wide, if the active theme has declared support. At the moment, users can set the base and headings fonts.
4
-
5
- - [How to develop and build the plugin](#how-to-develop-and-build-the-plugin)
6
- - [How it works and how themes can use it](#how-it-works-and-how-themes-can-use-it)
7
- - [Fallbacks for browsers without support for CSS custom properties](#fallbacks-for-browsers-without-support-for-css-custom-properties)
8
- - [How to add a "Theme Default" option to the font list](#how-to-add-a-theme-default-option-to-the-font-list)
9
- - [How to use a fallback stylesheet (experimental)](#how-to-use-a-fallback-stylesheet-experimental)
10
- - [Existing hooks](#existing-hooks)
11
- - [jetpack_global_styles_data_set_get_data filter](#jetpack_global_styles_data_set_get_data-filter)
12
- - [jetpack_global_styles_data_set_save_data filter](#jetpack_global_styles_data_set_save_data-filter)
13
- - [jetpack_global_styles_permission_check_additional filter](#jetpack_global_styles_permission_check_additional-filter)
14
- - [jetpack_global_styles_settings](#jetpack_global_styles_settings)
15
- - [FAQ](#faq)
16
- - [Which fonts are available?](#which-fonts-are-available)
17
- - [What will happen when the user changes to another theme that supports GlobalStyles?](#what-will-happen-when-the-user-changes-to-another-theme-that-supports-globalstyles)
18
- - [What will happen when the user changes to a theme that doesn't support Global Styles or the plugin is deactivated?](#what-will-happen-when-the-user-changes-to-a-theme-that-doesnt-support-global-styles-or-the-plugin-is-deactivated)
19
-
20
- ## How to develop and build the plugin
21
-
22
- Refer to instructions in the top-level [Full Site Editing](https://github.com/automattic/wp-calypso/tree/master/apps/full-site-editing) directory.
23
-
24
- ## How it works and how themes can use it
25
-
26
- This plugin creates a new sidebar for the block editor through which the users can update the styles site-wide. At the moment, users can set the base and headings fonts. For the sidebar to be shown, the active theme needs to have declared support:
27
-
28
- ```php
29
- add_theme_support( 'jetpack-global-styles' );
30
- ```
31
-
32
- The user choices are stored using the Options API in the WordPress database, and exposed in the block editor and the front end as CSS custom properties. For example, the base and headings fonts are exposed as `--font-base` and `--font-headings`, respectively.
33
-
34
- The theme can then use those variables to set its styles:
35
-
36
- ```css
37
- body {
38
- font-family: var( --font-base, serif );
39
- }
40
-
41
- h1 {
42
- font-family: var( --font-headings, sans-serif );
43
- }
44
- ```
45
-
46
- In the above example, the `body`'s font-family will be what the user selected as the base font, or `serif` if `--font-base` is not set. Likewise, the `h1`'s font-family will be what the user selected as the headings font, or `sans-serif` if `--font-headings` is not set.
47
-
48
- **Fallback values for CSS Custom Properties**
49
-
50
- Note the font-family fallbacks provided for when `--font-base` or `--font-headings` are not set. There are a number of situations where these variables can have the value `unset` or even not being present (which the browsers also consider as being `unset`):
51
-
52
- - If the Global Styles plugin is not installed, activated, or the theme didn't declared support.
53
- - If the Global Styles plugin is activated and the theme has declared support but:
54
- - the user hasn't selected and saved any choice yet.
55
- - the user has selected _Theme Default_ as the font.
56
-
57
- By adding fallbacks for these situations, themes can work with or without Global Styles using the same styles. They also provide a better experience to users with good defaults that are overwritten by user's choices when necessary. This is the recommended way to use the Global Styles plugin.
58
-
59
- What would happen if no fallback is provided?
60
-
61
- ```css
62
- body {
63
- font-family: var( --font-base );
64
- }
65
-
66
- h1 {
67
- font-family: var( --font-headings );
68
- }
69
- ```
70
-
71
- In the above example, the `body`'s font-family will be what the user selected as the base font, or `inherit` if `--font-base` is not set. Likewise, the `h1`'s font-family will be what the user selected as the headings font, or `inherit` if `--font-headings` is not set.
72
-
73
- For more info on CSS Custom Properties, check out:
74
-
75
- - [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/--*).
76
- - [CSS Working Group specification](https://drafts.csswg.org/css-variables/#defining-variables).
77
- - The [unset](https://drafts.csswg.org/css-cascade-4/#valdef-all-unset) keyword.
78
-
79
- ### Fallbacks for browsers without support for CSS custom properties
80
-
81
- Browsers that don't support CSS custom properties don't know what to do with the `var` statement (neither the fallback within), so they ignore it. We can leverage this to provide fallbacks for them as well:
82
-
83
- ```css
84
- body {
85
- font-family: serif; // Fallback for browsers without support.
86
- font-family: var( --font-base, serif ); // Variable and fallback for browsers with support.
87
- }
88
-
89
- h1 {
90
- font-family: sans-serif; // Fallback for browsers without support.
91
- font-family: var( --font-headings, sans-serif ); // Variable and fallback for browsers with support.
92
- }
93
- ```
94
-
95
- ### How to add a "Theme Default" option to the font list
96
-
97
- Themes can opt-in to add a _Theme Default_ option via the `enable_theme_default` parameter:
98
-
99
- ```php
100
- add_theme_support(
101
- 'jetpack-global-styles',
102
- [
103
- 'enable_theme_default' => true,
104
- ]
105
- );
106
- ```
107
-
108
- This will add a new option in the font picker called _Theme Default_. If the user hasn't selected any yet, it will be the active option by default (if the theme didn't add this option, the _System Font_ will be picked instead). When _Theme Default_ is active, the corresponding CSS custom property value will be `unset`.
109
-
110
- For example, if the user selects:
111
-
112
- - the base font to _Theme Default_, then `--font-base` value will be `unset`
113
- - the headings font to _Lora_, then `--font-headings` value will be `Lora`
114
-
115
- Essentially, the _Theme Default_ option is how an user would reset their choices and get back the theme default styles. We recommend adding this option and using fallbacks in the CSS custom properties declarations.
116
-
117
- ### How to use a fallback stylesheet (experimental)
118
-
119
- As an experimental feature, the Global Styles plugin can provide a fallback stylesheet that uses the CSS custom properties. This is so themes can use Global Styles without introducing any changes to its own stylesheet.
120
-
121
- ```php
122
- add_theme_support(
123
- 'jetpack-global-styles',
124
- [
125
- 'enqueue_experimental_styles' => true,
126
- ]
127
- );
128
- ```
129
-
130
- If the `enqueue_experimental_styles` is present and it's `true`, the plugin will enqueue a fallback stylesheet that overrides the theme's. This feature is experimental. The overrides can't take into account all the ways that themes can present information (different tags, classes, etc.), so themes are responsible to check these are enough for its use case.
131
-
132
- Note that if the theme requests enqueueing the experimental stylesheet, the experimental Global Styles styles will override the theme ones once the plugin is activated. By default, until the user makes a font choice, the _System Font_ will be used.
133
-
134
- **_Theme Default_ option**
135
-
136
- Themes that use this experimental feature can also add a _Theme Default_ option in the font picker by setting the `enable_theme_default` property to true. Note that when the user selects _Theme Default_ the font to be used is _System Font_. Per se, this isn't very useful, however, themes can also provide fallback fonts for when the font is `unset` (the user selected _Theme Default_ or hasn't made any choice yet):
137
-
138
- ```php
139
- add_theme_support(
140
- 'jetpack-global-styles',
141
- [
142
- 'enqueue_experimental_styles' => true,
143
- 'enable_theme_default' => true,
144
- 'font_base' => 'serif',
145
- 'font_headings' => 'sans-serif',
146
- ]
147
- );
148
- ```
149
-
150
- ## Existing hooks
151
-
152
- ### jetpack_global_styles_data_set_get_data filter
153
-
154
- See [README-DATA.md](./README-DATA.md).
155
-
156
- ### jetpack_global_styles_data_set_save_data filter
157
-
158
- See [README-DATA.md](./README-DATA.md).
159
-
160
- ### jetpack_global_styles_permission_check_additional filter
161
-
162
- This filter can be used to add _an additional check_ to decide whether 1) the global styles sidebar is enqueued and 2) the REST API endpoint should return the data. Note the existing checks in place:
163
-
164
- - The user is logged in and has the `customize` capability.
165
- - The site uses a theme that has declared support for `jetpack-global-styles`.
166
-
167
- ```php
168
- function permission_check_callback( $has_permissions ) {
169
- if ( $some_condition ) {
170
- return false;
171
- }
172
- return $has_permissions;
173
- }
174
- add_filter( 'jetpack_global_styles_permission_check_additional', permission_check_callback );
175
- ```
176
-
177
- ### jetpack_global_styles_settings
178
-
179
- This filter can be used to configure any of the Global Styles settings.
180
-
181
- REST API related:
182
-
183
- - `rest_namespace`: REST API namespace.
184
- - `rest_route`: REST API route.
185
- - `rest_path_client`: the path to be used by the client to query the endpoint.
186
-
187
- To white-label Global Styles:
188
-
189
- - `theme_support`: the name of the theme support feature.
190
- - `option_name`: the name of the option to use in the database.
191
- - `redux_store_name`: the name of the custom Redux store used by the client.
192
- - `plugin_name`: the name of the registered plugin for the block editor.
193
-
194
- ## FAQ
195
-
196
- ### Which fonts are available?
197
-
198
- These are the fonts available via the font selector in the sidebar and for the themes to set as defaults:
199
-
200
- - Arvo
201
- - Cabin
202
- - Chivo
203
- - Domine
204
- - Fira Sans
205
- - Libre Baskerville
206
- - Libre Franklin
207
- - Lora
208
- - Merriweather
209
- - Montserrat
210
- - Open Sans
211
- - Playfair Display
212
- - Poppins
213
- - Roboto
214
- - Roboto Slab
215
- - Rubik
216
- - Source Sans Pro
217
- - Source Serif Pro
218
- - Space Mono
219
- - Work Sans
220
-
221
- ### What will happen when the user changes to another theme that supports GlobalStyles?
222
-
223
- Everything will continue to work as expected. If the user had selected:
224
-
225
- - The _Theme Default_ option, the new theme's font will be used instead of the old one.
226
- - A _custom font_, it'll still be used in the new theme. Note, however, that themes can make different choices as to what they consider base and font selections. For example: a theme can use the headings font for quotes and another theme can use the base font.
227
-
228
- ### What will happen when the user changes to a theme that doesn't support Global Styles or the plugin is deactivated?
229
-
230
- The theme's font will be used.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/global-styles/class-global-styles.php DELETED
@@ -1,515 +0,0 @@
1
- <?php
2
- /**
3
- * Global Styles file.
4
- *
5
- * @package Automattic\Jetpack\Global_Styles
6
- */
7
-
8
- namespace Automattic\Jetpack\Global_Styles;
9
-
10
- /**
11
- * Class Global_Styles
12
- */
13
- class Global_Styles {
14
-
15
- /**
16
- * Class instance.
17
- *
18
- * @var \Automattic\Jetpack\Global_Styles\Global_Styles
19
- */
20
- private static $instance = null;
21
-
22
- /**
23
- * Holds the internal data description to be exposed through REST API.
24
- *
25
- * @var \Automattic\Jetpack\Global_Styles\Data_Set
26
- */
27
- private $rest_api_data;
28
-
29
- /**
30
- * Namespace to use for the REST Endpoint.
31
- * This can be overrided at initialization.
32
- *
33
- * @var string
34
- */
35
- private $rest_namespace = 'jetpack-global-styles/v1';
36
-
37
- /**
38
- * Route to use for the REST Route.
39
- * This can be overrided at initialization.
40
- *
41
- * @var string
42
- */
43
- private $rest_route = 'options';
44
-
45
- /**
46
- * Path the client will use to work with the options.
47
- * This can be overrided at initialization.
48
- *
49
- * @var string
50
- */
51
- private $rest_path_client = 'jetpack-global-styles/v1/options';
52
-
53
- /**
54
- * Undocumented variable
55
- *
56
- * @var string
57
- */
58
- private $theme_support = 'jetpack-global-styles';
59
-
60
- /**
61
- * Undocumented variable
62
- *
63
- * @var string
64
- */
65
- private $option_name = 'jetpack_global_styles';
66
-
67
- /**
68
- * Undocumented variable
69
- *
70
- * @var string
71
- */
72
- private $redux_store_name = 'jetpack/global-styles';
73
-
74
- /**
75
- * Undocumented variable
76
- *
77
- * @var string
78
- */
79
- private $plugin_name = 'jetpack-global-styles';
80
-
81
- const VERSION = '1909241817';
82
-
83
- const SYSTEM_FONT = '-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif';
84
- const AVAILABLE_FONTS = [
85
- [
86
- 'label' => 'Theme Default',
87
- 'value' => 'unset',
88
- ],
89
- [
90
- 'label' => 'System Font',
91
- 'value' => self::SYSTEM_FONT,
92
- ],
93
- 'Arvo',
94
- 'Cabin',
95
- 'Chivo',
96
- 'Domine',
97
- 'Fira Sans',
98
- 'Libre Baskerville',
99
- 'Libre Franklin',
100
- 'Lora',
101
- 'Merriweather',
102
- 'Montserrat',
103
- 'Open Sans',
104
- 'Playfair Display',
105
- 'Poppins',
106
- 'Roboto',
107
- 'Roboto Slab',
108
- 'Rubik',
109
- 'Source Sans Pro',
110
- 'Source Serif Pro',
111
- 'Space Mono',
112
- 'Work Sans',
113
- ];
114
-
115
- /**
116
- * Creates instance.
117
- *
118
- * @return \Automattic\Jetpack\Global_Styles\Global_Styles
119
- */
120
- public static function init() {
121
- if ( is_null( self::$instance ) ) {
122
- self::$instance = new self();
123
- }
124
-
125
- return self::$instance;
126
- }
127
-
128
- /**
129
- * Global Styles setup.
130
- */
131
- public function __construct() {
132
- $this->update_plugin_settings();
133
-
134
- // DATA TO EXPOSE THROUGH THE REST API.
135
- require_once __DIR__ . '/includes/class-data-set.php';
136
- $this->rest_api_data = new Data_Set(
137
- [
138
- 'blogname' => [
139
- 'type' => 'option',
140
- 'name' => 'blogname',
141
- 'default' => 'Your site name',
142
- ],
143
- 'font_base' => [
144
- 'type' => 'option',
145
- 'name' => [ 'jetpack_global_styles', 'font_base' ],
146
- 'default' => 'unset',
147
- 'updatable' => true,
148
- ],
149
- 'font_headings' => [
150
- 'type' => 'option',
151
- 'name' => [ 'jetpack_global_styles', 'font_headings' ],
152
- 'default' => 'unset',
153
- 'updatable' => true,
154
- ],
155
- 'font_base_default' => [
156
- 'type' => 'theme',
157
- 'name' => [ 'jetpack-global-styles', 'font_base' ],
158
- 'default' => self::SYSTEM_FONT,
159
- ],
160
- 'font_headings_default' => [
161
- 'type' => 'theme',
162
- 'name' => [ 'jetpack-global-styles', 'font_headings' ],
163
- 'default' => self::SYSTEM_FONT,
164
- ],
165
- 'font_options' => [
166
- 'type' => 'literal',
167
- 'default' => self::AVAILABLE_FONTS,
168
- ],
169
- 'font_pairings' => [
170
- 'type' => 'literal',
171
- 'default' => [
172
- [
173
- 'label' => 'Playfair Display & Roboto',
174
- 'headings' => 'Playfair Display',
175
- 'base' => 'Roboto',
176
- 'preview' => 'PLAY_ROBOTO', // See font-pairings-panel-previews.js.
177
- ],
178
- [
179
- 'label' => 'Rubik & Work Sans',
180
- 'headings' => 'Rubik',
181
- 'base' => 'Work Sans',
182
- 'preview' => 'RUBIK_WORK', // See font-pairings-panel-previews.js.
183
- ],
184
- [
185
- 'label' => 'System Font & Libre Baskerville',
186
- 'headings' => self::SYSTEM_FONT,
187
- 'base' => 'Libre Baskerville',
188
- 'preview' => 'SYSTEM_BASKER', // See font-pairings-panel-previews.js.
189
- ],
190
- [
191
- 'label' => 'Space Mono & Lora',
192
- 'headings' => 'Space Mono',
193
- 'base' => 'Lora',
194
- 'preview' => 'SPACE_LORA', // See font-pairings-panel-previews.js.
195
- ],
196
- ],
197
- ],
198
- ]
199
- );
200
-
201
- // Setup REST API for the editor. Some environments (WordPress.com)
202
- // may not load the theme functions for REST API calls,
203
- // so we need to initialize it independently of theme support.
204
- add_action( 'rest_api_init', [ $this, 'rest_api_init' ] );
205
-
206
- add_filter( 'jetpack_global_styles_data_set_get_data', [ $this, 'maybe_filter_font_list' ] );
207
- add_filter( 'jetpack_global_styles_data_set_save_data', [ $this, 'filter_and_validate_font_options' ] );
208
-
209
- // Setup editor.
210
- if ( $this->can_use_global_styles() ) {
211
- add_action(
212
- 'enqueue_block_editor_assets',
213
- [ $this, 'enqueue_block_editor_assets' ]
214
- );
215
- add_filter(
216
- 'block_editor_settings',
217
- [ $this, 'block_editor_settings' ],
218
- PHP_INT_MAX // So it runs last and overrides any style provided by the theme.
219
- );
220
- }
221
-
222
- // Setup front-end.
223
- add_action(
224
- 'wp_enqueue_scripts',
225
- [ $this, 'wp_enqueue_scripts' ],
226
- PHP_INT_MAX // So it runs last and overrides any style provided by the theme.
227
- );
228
- }
229
-
230
- /**
231
- * Let 3rd parties configure plugin settings.
232
- */
233
- private function update_plugin_settings() {
234
- $settings = apply_filters(
235
- 'jetpack_global_styles_settings',
236
- [
237
- // Server-side settings.
238
- 'rest_namespace' => $this->rest_namespace,
239
- 'rest_route' => $this->rest_route,
240
- 'theme_support' => $this->theme_support,
241
- 'option_name' => $this->option_name,
242
- // Client-side settings.
243
- 'rest_path_client' => $this->rest_path_client,
244
- 'redux_store_name' => $this->redux_store_name,
245
- 'plugin_name' => $this->plugin_name,
246
- ]
247
- );
248
-
249
- $this->rest_namespace = $settings['rest_namespace'];
250
- $this->rest_route = $settings['rest_route'];
251
- $this->theme_support = $settings['theme_support'];
252
- $this->option_name = $settings['option_name'];
253
- $this->rest_path_client = $settings['rest_path_client'];
254
- $this->redux_store_name = $settings['redux_store_name'];
255
- $this->plugin_name = $settings['plugin_name'];
256
- }
257
-
258
- /**
259
- * Initialize REST API endpoint.
260
- */
261
- public function rest_api_init() {
262
- require_once __DIR__ . '/includes/class-json-endpoint.php';
263
- $rest_api = new JSON_Endpoint(
264
- $this->rest_namespace,
265
- $this->rest_route,
266
- $this->rest_api_data,
267
- [ $this, 'can_use_global_styles' ]
268
- );
269
- $rest_api->setup();
270
- }
271
-
272
- /**
273
- * Whether we should load Global Styles
274
- * per this user and site.
275
- *
276
- * @return boolean
277
- */
278
- public function can_use_global_styles() {
279
- return is_user_logged_in() &&
280
- current_user_can( 'customize' ) &&
281
- current_theme_supports( $this->theme_support ) &&
282
- apply_filters( 'jetpack_global_styles_permission_check_additional', true );
283
- }
284
-
285
- /**
286
- * We want the front-end styles enqueued in the editor
287
- * and wrapped by the .editor-styles-wrapper class,
288
- * so they don't bleed into other parts of the editor.
289
- *
290
- * We also want the global styles to override the theme's stylesheet.
291
- * We do so by hooking into the block_editor_settings
292
- * and append this style the last.
293
- *
294
- * @param array $settings The editor settings.
295
- *
296
- * @return $settings array with the inline styles added.
297
- */
298
- public function block_editor_settings( $settings ) {
299
- if ( empty( $settings['styles'] ) || ! is_array( $settings['styles'] ) ) {
300
- $settings['styles'] = array();
301
- }
302
-
303
- // Append them last, so it overrides any existing inline styles.
304
- $settings['styles'][] = array(
305
- 'css' => $this->get_inline_css(),
306
- );
307
-
308
- return $settings;
309
- }
310
-
311
- /**
312
- * Enqueues the assets for the editor.
313
- *
314
- * @return void
315
- */
316
- public function enqueue_block_editor_assets() {
317
- $asset_file = plugin_dir_path( __FILE__ ) . 'dist/global-styles.asset.php';
318
- $asset = file_exists( $asset_file )
319
- ? require_once $asset_file
320
- : null;
321
- $dependencies = isset( $asset['dependencies'] ) ?
322
- $asset['dependencies'] :
323
- [];
324
- $version = isset( $asset['version'] ) ?
325
- $asset['version'] :
326
- filemtime( plugin_dir_path( __FILE__ ) . 'dist/global-styles.js' );
327
-
328
- wp_enqueue_script(
329
- 'jetpack-global-styles-editor-script',
330
- plugins_url( 'dist/global-styles.js', __FILE__ ),
331
- $dependencies,
332
- $version,
333
- true
334
- );
335
- wp_localize_script(
336
- 'jetpack-global-styles-editor-script',
337
- 'JETPACK_GLOBAL_STYLES_EDITOR_CONSTANTS',
338
- [
339
- 'PLUGIN_NAME' => $this->plugin_name,
340
- 'REST_PATH' => $this->rest_path_client,
341
- 'STORE_NAME' => $this->redux_store_name,
342
- ]
343
- );
344
- wp_enqueue_style(
345
- 'jetpack-global-styles-editor-style',
346
- plugins_url( 'dist/global-styles.css', __FILE__ ),
347
- [],
348
- filemtime( plugin_dir_path( __FILE__ ) . 'dist/global-styles.css' )
349
- );
350
- }
351
-
352
- /**
353
- * Enqueues the assets for front-end.
354
- *
355
- * We want the global styles to override the theme's stylesheet,
356
- * that's why they are inlined.
357
- *
358
- * @return void
359
- */
360
- public function wp_enqueue_scripts() {
361
- wp_enqueue_style(
362
- 'jetpack-global-styles-frontend-style',
363
- plugins_url( 'static/blank.css', __FILE__ ),
364
- [],
365
- self::VERSION // To bust cache when changes are done to font list, css custom vars, or style.css.
366
- );
367
- wp_add_inline_style( 'jetpack-global-styles-frontend-style', $this->get_inline_css( true ) );
368
- }
369
-
370
- /**
371
- * Prepare the inline CSS.
372
- *
373
- * @param boolean $only_selected_fonts Whether it should load all the fonts or only the selected. False by default.
374
- * @return string
375
- */
376
- private function get_inline_css( $only_selected_fonts = false ) {
377
- $result = '';
378
-
379
- $data = $this->rest_api_data->get_data();
380
-
381
- /*
382
- * Add the fonts we need:
383
- *
384
- * - all of them for the backend
385
- * - only the selected ones for the frontend
386
- */
387
- $font_list = [];
388
- // We want $font_list to only contain valid Google Font values,
389
- // so we filter out things like 'unset' on the system font.
390
- $font_values = array_diff( $this->get_font_values( $data['font_options'] ), [ 'unset', self::SYSTEM_FONT ] );
391
- if ( true === $only_selected_fonts ) {
392
- foreach ( [ 'font_base', 'font_base_default', 'font_headings', 'font_headings_default' ] as $key ) {
393
- if ( in_array( $data[ $key ], $font_values, true ) ) {
394
- $font_list[] = $data[ $key ];
395
- }
396
- }
397
- } else {
398
- $font_list = $font_values;
399
- }
400
-
401
- if ( count( $font_list ) > 0 ) {
402
- $font_list_str = '';
403
- foreach ( $font_list as $font ) {
404
- // Some fonts lack italic variants,
405
- // the API will return only the regular and bold CSS for those.
406
- $font_list_str = $font_list_str . $font . ':regular,bold,italic,bolditalic|';
407
- }
408
- $result = $result . "@import url('https://fonts.googleapis.com/css?family=" . $font_list_str . "');";
409
- }
410
-
411
- /*
412
- * Add the CSS custom properties.
413
- *
414
- * Note that we transform var_name into var-name,
415
- * so the output is:
416
- *
417
- * :root{
418
- * --var-name-1: value;
419
- * --var-name-2: value;
420
- * }
421
- *
422
- */
423
- $result = $result . ':root {';
424
- $value = '';
425
- $keys = [ 'font_headings', 'font_base', 'font_headings_default', 'font_base_default' ];
426
- foreach ( $keys as $key ) {
427
- $value = $data[ $key ];
428
- $result = $result . ' --' . str_replace( '_', '-', $key ) . ': ' . $value . ';';
429
- }
430
- $result = $result . '}';
431
-
432
- /*
433
- * If the theme opts-in, also add a default stylesheet
434
- * that uses the CSS custom properties.
435
- *
436
- * This is a fallback mechanism in case there are themes
437
- * we don't want to / can't migrate to use CSS vars.
438
- */
439
- $theme_support = get_theme_support( $this->theme_support )[0];
440
- if (
441
- is_array( $theme_support ) &&
442
- array_key_exists( 'enqueue_experimental_styles', $theme_support ) &&
443
- true === $theme_support['enqueue_experimental_styles']
444
- ) {
445
- $result = $result . file_get_contents( plugin_dir_path( __FILE__ ) . 'static/style.css', true );
446
- }
447
-
448
- return $result;
449
- }
450
-
451
- /**
452
- * Callback for get data filter.
453
- *
454
- * @param array $result Data to be sent through the REST API.
455
- *
456
- * @return array Filtered result.
457
- */
458
- public function maybe_filter_font_list( $result ) {
459
- $theme_defaults = get_theme_support( $this->theme_support )[0];
460
- if (
461
- array_key_exists( 'font_options', $result ) &&
462
- (
463
- ! is_array( $theme_defaults ) ||
464
- ! array_key_exists( 'enable_theme_default', $theme_defaults ) ||
465
- true !== $theme_defaults['enable_theme_default']
466
- )
467
- ) {
468
- $result['font_options'] = array_slice( $result['font_options'], 1 );
469
- }
470
-
471
- return $result;
472
- }
473
-
474
- /**
475
- * Return the list of available font values.
476
- *
477
- * @param array $font_list Array of fonts to process.
478
- * @return array Font values.
479
- */
480
- private function get_font_values( $font_list ) {
481
- $font_values = [];
482
- foreach ( $font_list as $font ) {
483
- if ( is_array( $font ) ) {
484
- $font_values[] = $font['value'];
485
- } else {
486
- $font_values[] = $font;
487
- }
488
- }
489
- return $font_values;
490
- }
491
-
492
- /**
493
- * Callback for save data filter.
494
- *
495
- * @param array $incoming_data The data to validate.
496
- * @return array Filtered result.
497
- */
498
- public function filter_and_validate_font_options( $incoming_data ) {
499
- $result = [];
500
-
501
- $font_values = $this->get_font_values( self::AVAILABLE_FONTS );
502
- foreach ( [ 'font_base', 'font_headings' ] as $key ) {
503
- if (
504
- array_key_exists( $key, $incoming_data ) &&
505
- in_array( $incoming_data[ $key ], $font_values, true )
506
- ) {
507
- $result[ $key ] = $incoming_data[ $key ];
508
- }
509
- }
510
-
511
- return $result;
512
- }
513
- }
514
-
515
- add_action( 'init', [ __NAMESPACE__ . '\Global_Styles', 'init' ] );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/global-styles/dist/global-styles.asset.php DELETED
@@ -1 +0,0 @@
1
- <?php return array('dependencies' => array('wp-api-fetch', 'wp-components', 'wp-compose', 'wp-data', 'wp-dom-ready', 'wp-edit-post', 'wp-element', 'wp-i18n', 'wp-keycodes', 'wp-plugins', 'wp-polyfill'), 'version' => '603bed5808f28d5f465cf89f412ee922');
 
trunk/global-styles/dist/global-styles.css DELETED
@@ -1 +0,0 @@
1
- .global-styles-sidebar .components-select-control__input{line-height:1;font-size:18px;height:36px}.global-styles-sidebar h3{margin:0 0 1em}.global-styles-sidebar__panel-action-buttons{display:flex;justify-content:flex-end;margin-bottom:96px}.global-styles-sidebar__publish-button{margin-left:1em}.font-pairings-panel{cursor:pointer;border-radius:4px;padding:4px;margin-bottom:.5em}.font-pairings-panel.is-selected{box-shadow:0 0 0 2px #555d66}.font-pairings-panel:focus{box-shadow:0 0 0 2px #00a0d2}.font-pairings-panel:hover{background-color:#f3f4f5;color:#191e23}.font-pairings-panel__preview{border:1px solid rgba(25,30,35,.2);border-radius:4px;background-color:#fff;padding:4px}.font-pairings-panel__preview h1,.font-pairings-panel__preview p{margin:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding:10px 0}.font-pairings-panel__preview svg{display:block;width:100%;height:auto}.font-pairings-panel__label{text-align:center;margin-bottom:0}
 
trunk/global-styles/dist/global-styles.js DELETED
@@ -1,2 +0,0 @@
1
- /*! For license information please see global-styles.js.LICENSE */
2
- !function(e,t){for(var c in t)e[c]=t[c]}(window,function(e){var t={};function c(n){if(t[n])return t[n].exports;var a=t[n]={i:n,l:!1,exports:{}};return e[n].call(a.exports,a,a.exports,c),a.l=!0,a.exports}return c.m=e,c.c=t,c.d=function(e,t,n){c.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},c.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},c.t=function(e,t){if(1&t&&(e=c(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(c.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var a in e)c.d(n,a,function(t){return e[t]}.bind(null,a));return n},c.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return c.d(t,"a",t),t},c.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},c.p="",c(c.s=14)}([function(e,t){!function(){e.exports=this.wp.element}()},function(e,t){!function(){e.exports=this.wp.components}()},function(e,t){!function(){e.exports=this.wp.i18n}()},function(e,t){!function(){e.exports=this.wp.data}()},function(e,t){e.exports=function(e,t,c){return t in e?Object.defineProperty(e,t,{value:c,enumerable:!0,configurable:!0,writable:!0}):e[t]=c,e}},function(e,t){!function(){e.exports=this.wp.editPost}()},function(e,t,c){var n=c(4);function a(e,t){var c=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),c.push.apply(c,n)}return c}e.exports=function(e){for(var t=1;t<arguments.length;t++){var c=null!=arguments[t]?arguments[t]:{};t%2?a(Object(c),!0).forEach((function(t){n(e,t,c[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(c)):a(Object(c)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(c,t))}))}return e}},function(e,t){!function(){e.exports=this.wp.apiFetch}()},function(e,t){!function(){e.exports=this.wp.plugins}()},function(e,t){!function(){e.exports=this.wp.compose}()},function(e,t){!function(){e.exports=this.wp.domReady}()},function(e,t){!function(){e.exports=this.wp.keycodes}()},function(e,t,c){var n;!function(){"use strict";var c={}.hasOwnProperty;function a(){for(var e=[],t=0;t<arguments.length;t++){var n=arguments[t];if(n){var r=typeof n;if("string"===r||"number"===r)e.push(n);else if(Array.isArray(n)&&n.length){var l=a.apply(null,n);l&&e.push(l)}else if("object"===r)for(var o in n)c.call(n,o)&&n[o]&&e.push(o)}}return e.join(" ")}e.exports?(a.default=a,e.exports=a):void 0===(n=function(){return a}.apply(t,[]))||(e.exports=n)}()},function(e,t,c){},function(e,t,c){"use strict";c.r(t);var n,a,r,l,o=c(8),s=c(3),i=c(9),u=c(6),h=c.n(u),f=c(7),p=c.n(f),v={},b=!1,O={publishOptions:regeneratorRuntime.mark((function e(t){return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,{type:"IO_PUBLISH_OPTIONS",options:t};case 2:return e.abrupt("return",{type:"PUBLISH_OPTIONS",options:t});case 3:case"end":return e.stop()}}),e)})),updateOptions:function(e){return{type:"UPDATE_OPTIONS",options:e}},fetchOptions:function(){return{type:"IO_FETCH_OPTIONS"}},resetLocalChanges:function(){return{type:"RESET_OPTIONS",options:v}}},m=c(10),d=c.n(m),g=c(4),j=c.n(g),_=c(0),E=c(5),z=c(1),y=c(2),P=c(11),w=c(12),V=c.n(w),S=function(e){var t=e.unsupportedFeature;return Object(_.createElement)("p",null,Object(y.sprintf)(Object(y.__)("Your active theme doesn't support %s."),t))},H=function(e,t,c){switch(e){case"SPACE_LORA":return Object(_.createElement)(z.SVG,{width:"232",height:"132",viewBox:"0 0 232 132",xmlns:"http://www.w3.org/2000/svg"},Object(_.createElement)(z.Path,{fill:"#fa4d4b",d:"M0 0h232v132H0z"}),Object(_.createElement)(z.Path,{d:"M24.1 62c-3.6-2.9-8.9-5-15.8-6.3-2.8-.5-5-1-6.9-1.6-.5-.2-1-.3-1.5-.5v12.5c1.4.3 2.9.6 4.4.9 2.5.4 4.6 1 6.2 1.6s2.9 1.3 3.9 2.2c.9.8 1.6 1.6 2 2.6.4.9.6 1.9.6 3 0 2.3-.9 4.2-2.7 5.8-1.8 1.6-4.6 2.4-8.4 2.4-2.2 0-4.2-.3-5.9-.8v12c1.8.3 3.7.4 5.7.4 3.7 0 7-.5 10-1.4 2.9-.9 5.5-2.3 7.5-4s3.6-3.9 4.7-6.3c1.1-2.5 1.7-5.3 1.7-8.4V75c0-5.7-1.8-10-5.5-13zM12.9 42.5c2.1 1.9 3.1 4.2 3.1 6.9v2.3h12.4v-3.4c0-2.7-.5-5.3-1.6-7.7-1-2.4-2.5-4.6-4.6-6.5-2-1.9-4.5-3.4-7.5-4.4-3-1.1-6.5-1.7-10.3-1.7-1.5 0-3 .1-4.4.3v11.9c1.3-.4 2.7-.5 4.4-.5 3.7-.2 6.5.8 8.5 2.8zm67.9 10.9c-1.8-2.1-4-3.6-6.5-4.7-2.4-1.1-5-1.6-7.8-1.6-3.7 0-6.7.7-9.1 2.2-2.4 1.4-4.2 3.4-5.5 5.9h-1.7v-6.8H38.4v65.4h11.8V88.2H52c.6 1.1 1.2 2.1 2 3.1.8.9 1.8 1.8 2.9 2.5 1.2.8 2.6 1.3 4.1 1.8 1.6.4 3.4.7 5.5.7 2.9 0 5.5-.5 8-1.5 2.5-1.1 4.7-2.6 6.5-4.6 1.8-2.1 3.3-4.6 4.3-7.5 1.1-2.9 1.6-6.3 1.6-10.2v-1.7c0-3.8-.6-7.1-1.7-10.1-1-2.9-2.5-5.3-4.4-7.3zm-5.7 18.9c0 3.9-1.2 7.1-3.5 9.4-2.3 2.3-5.2 3.4-8.9 3.4s-6.7-1.2-9-3.5c-2.3-2.4-3.4-5.5-3.4-9.3v-1.1c0-3.8 1.1-6.9 3.4-9.2 2.3-2.4 5.3-3.6 9-3.6s6.7 1.2 8.9 3.5c2.3 2.3 3.5 5.4 3.5 9.3v1.1zm66.2 8.6V48.4h-11.8V54h-1.7c-1.2-2.4-2.8-4.1-4.9-5.3-2-1.1-4.7-1.7-8-1.7-2.8 0-5.4.6-7.8 1.7-2.4 1.1-4.5 2.6-6.3 4.7-1.8 2.1-3.3 4.6-4.3 7.6-1.1 2.9-1.6 6.3-1.6 10v1.5c0 3.8.5 7.1 1.6 10.1 1.1 2.9 2.6 5.5 4.5 7.5 1.9 2.1 4 3.6 6.5 4.7s5.2 1.6 8 1.6c3 0 5.6-.6 7.9-1.8 2.3-1.3 4-3.4 5.3-6.3h1.7c0 2 .7 3.6 2 4.9 1.4 1.3 3.1 1.9 5.3 1.9h8.1V83.7H144c-1.8 0-2.7-.9-2.7-2.8zm-11.8-8.6c0 3.9-1 7.1-3.1 9.4-2.1 2.3-4.8 3.4-8.3 3.4-3.4 0-6.2-1.1-8.3-3.4-2.1-2.3-3.1-5.5-3.1-9.4v-1.1c0-3.9 1-7.1 3.1-9.3 2.1-2.3 4.8-3.5 8.3-3.5 3.4 0 6.2 1.2 8.3 3.5 2.1 2.3 3.1 5.4 3.1 9.3v1.1zm98.3-12.2c1.2-1 2.6-1.6 4.2-2V47.3c-2.1.3-4 .8-5.9 1.6-2.8 1.1-5.3 2.7-7.4 4.8-2.1 2.1-3.8 4.6-5.1 7.5-1.2 2.9-1.8 6.2-1.8 9.8v.6c0 3.9.6 7.4 1.7 10.4 1.2 3.1 2.8 5.7 4.9 7.8 2.1 2.1 4.6 3.8 7.5 4.9 1.9.7 4 1.2 6.1 1.5V84.7c-.4-.1-.7-.2-1.1-.3-1.3-.5-2.5-1.2-3.6-2-1-.9-1.8-1.9-2.4-3-.6-1.2-.9-2.5-.9-3.9h8V65.4h-7.8c.5-2 1.8-3.8 3.6-5.3zm-61.5 6.1c.7-1.7 1.6-3.1 2.7-4.2 1.1-1.2 2.4-2.1 3.9-2.7 1.5-.6 3.1-.9 4.8-.9 3.6 0 6.5 1 8.5 3s3.2 4.4 3.6 7.1l11.7-3c-1.1-5.5-3.6-10-7.7-13.3-4-3.4-9.3-5.1-15.8-5.1-3.4 0-6.6.6-9.6 1.7-2.9 1.1-5.5 2.8-7.8 4.9-2.2 2.1-3.9 4.7-5.2 7.7s-1.9 6.4-1.9 10.2v1.1c0 3.8.6 7.1 1.9 10.1 1.3 2.9 3 5.4 5.2 7.4s4.8 3.5 7.7 4.6c3 1.1 6.2 1.6 9.7 1.6 6.6 0 11.9-1.7 15.9-5.1 4-3.4 6.5-7.8 7.6-13.3l-11.7-3c-.6 3.1-1.8 5.5-3.8 7.3-1.9 1.8-4.6 2.7-8.3 2.7-1.7 0-3.3-.3-4.8-.8-1.5-.6-2.8-1.4-3.9-2.4-1.1-1.1-2-2.4-2.7-3.9-.6-1.6-.9-3.5-.9-5.5v-.6c0-2.1.3-3.9.9-5.6z",fill:"#270920"}),Object(_.createElement)(z.Path,{d:"M49.7 89.3c-1.1 1.3-2.6 2-4.5 2h-6.5c.1-1.1.2-2.5.2-4.3V68.5c0-1.3.1-2.2.4-2.8s.6-1 1.1-1.1c.5-.2 1.1-.3 2-.3v-3.2h-14v3.7l3.6-.1c-.1 1.1-.2 2.5-.2 4.4v18.5c0 1.3-.1 2.2-.4 2.8-.3.6-.6 1-1.1 1.2-.5.2-1.1.3-2 .3V95h25.8l.3-11.6h-3.2c.1 2.6-.5 4.5-1.5 5.9zM101.3 70c-2.5 0-4.8 1.5-7 4.5h-.1v-2.3c0-.8-.1-1.4-.1-1.9h-2.4c-.4.4-1.3.7-2.5 1-1.3.3-2.9.4-4.9.4v3.7l3.4-.1c-.1 1.3-.2 2.7-.2 4.1v8.1c0 1.5-.2 2.6-.5 3.3-.3.7-1.1 1-2.3 1V95h12.7v-3.7c-1.1 0-2.1 0-3.1.1.1-1.3.2-2.7.2-4.3v-7.9c.3-1 1-2.1 1.9-3.1 1-1.1 1.9-1.6 2.8-1.6.1 1 .5 1.8 1.1 2.2.6.4 1.4.6 2.2.6 1.1 0 1.9-.4 2.5-1.1.5-.7.8-1.5.8-2.3 0-1.3-.4-2.3-1.2-3-1-.5-2-.9-3.3-.9zm25.8 21.5c.1-1.3.2-2.7.2-4.3v-7.9c0-6.2-3-9.2-9-9.2-1.9 0-3.6.3-5.2.8-1.5.5-2.8 1.3-3.7 2.2-.9 1-1.4 2.1-1.4 3.3 0 .9.3 1.7.8 2.4.5.6 1.3.9 2.3.9 1 0 1.8-.3 2.3-.9.5-.6.8-1.3.8-2.1s-.2-1.4-.6-1.8c.9-.9 2.1-1.4 3.5-1.4 2.2 0 3.3 1.5 3.3 4.4v2.5c-3.7.2-6.9 1-9.5 2.5-2.6 1.5-4 3.6-4 6.4 0 1.9.6 3.4 1.7 4.6 1.2 1.2 2.8 1.8 4.8 1.8 2.8 0 5.2-1 7.2-3 .1 1.1.1 1.8.2 2.2h9.1v-3.7c-.7.1-1.8.2-2.8.3zm-6.6-2.2c-1.1 1.2-2.4 1.7-3.8 1.7-.8 0-1.4-.2-2-.6-.5-.4-.8-1.1-.8-1.9 0-1.3.6-2.4 1.8-3.1 1.3-.8 2.8-1.3 4.7-1.5v5.4zM75.1 71.5c-1.8-1-3.9-1.5-6.2-1.5-2.2 0-4.3.6-6.1 1.7-1.8 1.1-3.3 2.7-4.4 4.7-1.1 2-1.6 4.4-1.6 7 0 2.5.5 4.7 1.6 6.5 1.1 1.9 2.5 3.3 4.4 4.3 1.9 1 4 1.5 6.3 1.5 2.4 0 4.4-.5 6.2-1.6 1.8-1.1 3.3-2.6 4.3-4.6 1-2 1.5-4.3 1.5-7 0-2.5-.5-4.7-1.6-6.6-1.1-1.9-2.5-3.4-4.4-4.4zm-2.2 18.4c-.7 1.6-2 2.5-3.7 2.5-1.8 0-3.1-1-4-3-.9-2-1.3-4.4-1.3-7.2 0-2.5.4-4.5 1.2-6.2.8-1.7 2.1-2.5 3.9-2.5 1.7 0 3 1 3.8 3s1.2 4.4 1.2 7.2c-.1 2.5-.4 4.5-1.1 6.2z",fill:"#fff"}));case"SYSTEM_BASKER":return Object(_.createElement)(z.SVG,{width:"232",height:"132",viewBox:"0 0 232 132",xmlns:"http://www.w3.org/2000/svg"},Object(_.createElement)(z.Path,{fill:"#F18F1B",d:"M0 0h232v132H0z"}),Object(_.createElement)(z.Path,{d:"M10.016 50.563c.14 4.25 3.718 6.828 9.093 6.828 5.641 0 9.094-2.797 9.094-7.203 0-3.422-2.078-5.344-6.844-6.297l-2.39-.485c-2.657-.531-3.75-1.39-3.75-2.781 0-1.656 1.562-2.75 3.89-2.75 2.375 0 4.047 1.156 4.203 3.078h4.454c-.078-4.14-3.391-6.89-8.657-6.89-5.015 0-8.609 2.734-8.609 6.859 0 3.36 2.203 5.516 6.703 6.406l2.375.469c2.828.578 3.89 1.422 3.89 2.906 0 1.656-1.718 2.875-4.234 2.875-2.562 0-4.468-1.125-4.765-3.016h-4.453zM53 37v-8.422l7.86-14.125h-5.063l-5.063 9.625h-.109l-5.047-9.625h-5.14l7.843 14.125V37H53zM73.016 60.563c.14 4.25 3.718 6.828 9.093 6.828 5.641 0 9.094-2.797 9.094-7.204 0-3.421-2.078-5.343-6.844-6.296l-2.39-.485c-2.656-.531-3.75-1.39-3.75-2.781 0-1.656 1.562-2.75 3.89-2.75 2.375 0 4.047 1.156 4.204 3.078h4.453c-.079-4.14-3.391-6.89-8.657-6.89-5.015 0-8.609 2.734-8.609 6.859 0 3.36 2.203 5.516 6.703 6.406l2.375.469c2.828.578 3.89 1.422 3.89 2.906 0 1.656-1.718 2.875-4.234 2.875-2.562 0-4.468-1.125-4.765-3.016h-4.453zM114.984 47V28.344h6.532v-3.89H103.75v3.89h6.516V47h4.718zM149.812 43.094h-10.218v-5.688h9.64v-3.625h-9.64v-5.437h10.218v-3.89h-14.937V47h14.937v-3.906zM187.75 37V14.453h-5.469l-6.406 16.188h-.125l-6.406-16.188h-5.469V37h4.203V21.781h.125L174.328 37h2.969l6.125-15.219h.125V37h4.203z",fill:"#492B06"}),Object(_.createElement)(z.Path,{d:"M22.032 92H9.63v-.72c.396-.012.72-.048.972-.108s.444-.162.576-.306c.132-.144.222-.348.27-.612.048-.264.072-.606.072-1.026v-8.316c0-.42-.024-.756-.072-1.008-.036-.264-.114-.468-.234-.612a.852.852 0 0 0-.522-.306 4.454 4.454 0 0 0-.864-.126v-.72h6.21v.72a5.062 5.062 0 0 0-.99.108c-.24.06-.426.168-.558.324-.132.156-.222.372-.27.648a8.868 8.868 0 0 0-.054 1.098v7.542c0 .504.048.918.144 1.242.108.312.288.558.54.738.252.168.588.288 1.008.36.42.06.942.09 1.566.09.696 0 1.278-.042 1.746-.126.468-.084.858-.24 1.17-.468.324-.24.582-.558.774-.954.192-.396.354-.912.486-1.548h.72L22.032 92zm5.182-2.952c0 .48.018.864.054 1.152.036.288.108.51.216.666a.833.833 0 0 0 .468.324c.204.048.48.078.828.09V92h-5.67v-.72c.336-.012.606-.048.81-.108a.968.968 0 0 0 .486-.324c.12-.156.198-.366.234-.63.048-.276.072-.624.072-1.044V86.96c0-.696-.012-1.266-.036-1.71-.024-.456-.054-.768-.09-.936-.06-.3-.198-.498-.414-.594-.204-.096-.582-.144-1.134-.144v-.612l4.176-.684v6.768zm-2.646-10.584c0-.396.132-.726.396-.99a1.35 1.35 0 0 1 .99-.414c.396 0 .726.138.99.414.276.264.414.594.414.99 0 .384-.138.714-.414.99a1.343 1.343 0 0 1-.99.396c-.384 0-.714-.132-.99-.396a1.382 1.382 0 0 1-.396-.99zm8.574 9.594c0 .444.06.858.18 1.242.132.372.306.696.522.972.216.276.474.492.774.648.3.156.63.234.99.234.72 0 1.266-.33 1.638-.99.372-.66.558-1.632.558-2.916 0-1.248-.186-2.196-.558-2.844-.36-.66-.906-.99-1.638-.99-.432 0-.834.12-1.206.36-.36.228-.642.552-.846.972-.276.576-.414 1.302-.414 2.178v1.134zm-.036-4.356h.072a3.07 3.07 0 0 1 1.206-1.044c.492-.252 1.05-.378 1.674-.378.636 0 1.224.132 1.764.396.552.252 1.026.6 1.422 1.044.408.444.726.966.954 1.566.228.6.342 1.242.342 1.926 0 .72-.126 1.386-.378 1.998-.24.6-.576 1.122-1.008 1.566-.42.444-.918.792-1.494 1.044a4.362 4.362 0 0 1-1.8.378c-.66 0-1.284-.126-1.872-.378-.576-.264-1.038-.606-1.386-1.026L31.234 92h-.612V81.29c0-1.128-.078-1.902-.234-2.322a.93.93 0 0 0-.126-.216.488.488 0 0 0-.216-.144 1.07 1.07 0 0 0-.36-.108 7.62 7.62 0 0 0-.612-.108v-.612l4.032-.72v6.642zm12.759 5.508c0 .468.018.84.054 1.116.048.264.138.468.27.612.132.144.324.24.576.288.252.036.588.054 1.008.054V92H41.76v-.72c.36-.024.648-.06.864-.108.216-.048.378-.144.486-.288.108-.144.174-.348.198-.612.036-.276.054-.642.054-1.098v-2.196c0-.744-.018-1.338-.054-1.782-.036-.444-.114-.786-.234-1.026a.867.867 0 0 0-.522-.468c-.216-.084-.504-.126-.864-.126v-.63l3.6-.666.288 2.07h.072c.324-.636.75-1.14 1.278-1.512.528-.372 1.086-.558 1.674-.558.456 0 .828.114 1.116.342.288.228.432.516.432.864 0 .384-.114.708-.342.972-.216.264-.516.396-.9.396-.18 0-.342-.036-.486-.108a3.131 3.131 0 0 1-.396-.234 2.28 2.28 0 0 0-.342-.252.549.549 0 0 0-.342-.126c-.228 0-.444.15-.648.45-.204.3-.372.702-.504 1.206a9.68 9.68 0 0 0-.234 1.224c-.06.444-.09.888-.09 1.332v.864zM59.8 90.326c-1.092 1.236-2.454 1.854-4.086 1.854a5.787 5.787 0 0 1-2.034-.342c-.6-.24-1.116-.57-1.548-.99a4.592 4.592 0 0 1-1.008-1.53c-.24-.588-.36-1.242-.36-1.962 0-.744.126-1.422.378-2.034a4.619 4.619 0 0 1 1.062-1.602 5.01 5.01 0 0 1 1.638-1.062 5.62 5.62 0 0 1 2.088-.378c1.272 0 2.262.342 2.97 1.026.708.684 1.062 1.644 1.062 2.88 0 .192-.03.312-.09.36-.06.036-.228.054-.504.054h-5.796c-.048.108-.072.306-.072.594 0 1.176.252 2.106.756 2.79.516.684 1.212 1.026 2.088 1.026.504 0 1.002-.114 1.494-.342.504-.228.99-.552 1.458-.972l.504.63zm-3.492-4.734c.48 0 .786-.024.918-.072.144-.06.216-.192.216-.396 0-.528-.15-.96-.45-1.296a1.455 1.455 0 0 0-1.134-.504c-.516 0-.978.216-1.386.648-.396.42-.654.96-.774 1.62h2.61zM65.985 92v-.72a4.75 4.75 0 0 0 .972-.108c.252-.06.444-.162.576-.306.144-.144.24-.348.288-.612.048-.264.072-.606.072-1.026v-8.316c0-.42-.018-.756-.054-1.008-.036-.264-.114-.468-.234-.612a.755.755 0 0 0-.468-.306 3.572 3.572 0 0 0-.774-.126v-.72h5.778c1.812 0 3.204.294 4.176.882.984.576 1.476 1.404 1.476 2.484 0 1.428-1.026 2.436-3.078 3.024v.072c.66 0 1.254.096 1.782.288.54.18.996.438 1.368.774a3.523 3.523 0 0 1 1.17 2.682c0 .612-.15 1.146-.45 1.602-.288.456-.708.84-1.26 1.152-1.068.6-2.538.9-4.41.9h-6.93zm7.056-1.098c1.932 0 2.898-.87 2.898-2.61 0-1.068-.348-1.848-1.044-2.34-.36-.252-.828-.432-1.404-.54-.564-.108-1.26-.162-2.088-.162h-.864v3.6c0 .744.192 1.272.576 1.584.384.312 1.026.468 1.926.468zM71.6 84.17c.54 0 1.008-.048 1.404-.144a3.249 3.249 0 0 0 1.008-.45c.576-.396.864-1.014.864-1.854 0-.876-.216-1.506-.648-1.89-.432-.396-1.128-.594-2.088-.594h-1.278c-.216 0-.324.102-.324.306v4.626H71.6zm14.325 2.7c-1.008.456-1.77.882-2.286 1.278-.504.384-.756.786-.756 1.206 0 .348.096.624.288.828a.948.948 0 0 0 .72.306c.288 0 .558-.048.81-.144.252-.108.468-.246.648-.414.18-.168.318-.366.414-.594.108-.24.162-.492.162-.756v-1.71zm0-.954v-.756c0-.696-.126-1.2-.378-1.512-.24-.324-.618-.486-1.134-.486-.348 0-.612.096-.792.288-.18.18-.348.486-.504.918-.108.3-.264.534-.468.702-.192.168-.462.252-.81.252-.336 0-.594-.102-.774-.306-.18-.204-.27-.492-.27-.864 0-.576.312-1.032.936-1.368.636-.336 1.59-.504 2.862-.504 1.344 0 2.304.246 2.88.738.576.48.864 1.29.864 2.43v3.942c0 1.02.204 1.53.612 1.53a.978.978 0 0 0 .63-.234l.27.522c-.168.3-.432.54-.792.72a2.7 2.7 0 0 1-1.188.252c-.552 0-.972-.168-1.26-.504-.288-.336-.432-.81-.432-1.422h-.09c-.348.624-.798 1.098-1.35 1.422-.552.324-1.182.486-1.89.486-.756 0-1.362-.21-1.818-.63-.456-.432-.684-.99-.684-1.674 0-.528.234-1.02.702-1.476.468-.468 1.248-.924 2.34-1.368l2.538-1.098zM91.6 92h-.558v-3.276h.756c.204.864.498 1.494.882 1.89.384.396.882.594 1.494.594.444 0 .786-.09 1.026-.27a.923.923 0 0 0 .378-.774c0-.336-.15-.66-.45-.972-.3-.324-.786-.666-1.458-1.026-.912-.492-1.566-.978-1.962-1.458a2.574 2.574 0 0 1-.594-1.656c0-.396.072-.762.216-1.098.156-.348.36-.648.612-.9.264-.252.576-.444.936-.576.36-.144.75-.216 1.17-.216.372 0 .738.054 1.098.162.372.108.696.258.972.45l.324-.432h.468v2.718h-.702c-.276-.684-.564-1.176-.864-1.476-.288-.3-.642-.45-1.062-.45-.336 0-.606.09-.81.27-.192.18-.288.42-.288.72 0 .336.144.654.432.954.3.3.792.63 1.476.99.48.264.894.522 1.242.774s.63.51.846.774c.216.252.372.522.468.81.108.276.162.576.162.9 0 .42-.078.798-.234 1.134a2.462 2.462 0 0 1-.666.864c-.288.24-.636.426-1.044.558-.396.132-.84.198-1.332.198-.516 0-.996-.066-1.44-.198-.444-.144-.81-.348-1.098-.612L91.6 92zm13.299-.72c.384 0 .654-.012.81-.036.156-.036.234-.102.234-.198 0-.072-.084-.246-.252-.522-.156-.288-.36-.618-.612-.99l-1.368-2.052-.9.864v.702c0 .468.018.846.054 1.134.036.288.096.516.18.684a.759.759 0 0 0 .378.324c.168.06.378.09.63.09V92h-5.31v-.72c.336-.012.606-.048.81-.108a.969.969 0 0 0 .486-.306c.12-.156.198-.366.234-.63a6.4 6.4 0 0 0 .072-1.062v-7.632c0-.732-.012-1.308-.036-1.728-.024-.42-.09-.732-.198-.936a.647.647 0 0 0-.468-.396 3.877 3.877 0 0 0-.846-.072v-.666l4.014-.684v10.008l1.728-1.638a28.697 28.697 0 0 0 1.332-1.314c.264-.3.396-.516.396-.648 0-.108-.114-.18-.342-.216-.216-.048-.624-.072-1.224-.072v-.72h4.914v.72c-.456 0-.858.078-1.206.234-.348.156-.726.426-1.134.81l-1.746 1.638 3.114 4.41c.276.384.546.648.81.792.264.144.612.216 1.044.216V92h-5.598v-.72zm14.737-.954c-1.092 1.236-2.454 1.854-4.086 1.854a5.787 5.787 0 0 1-2.034-.342c-.6-.24-1.116-.57-1.548-.99a4.592 4.592 0 0 1-1.008-1.53c-.24-.588-.36-1.242-.36-1.962 0-.744.126-1.422.378-2.034a4.619 4.619 0 0 1 1.062-1.602 5.01 5.01 0 0 1 1.638-1.062 5.62 5.62 0 0 1 2.088-.378c1.272 0 2.262.342 2.97 1.026.708.684 1.062 1.644 1.062 2.88 0 .192-.03.312-.09.36-.06.036-.228.054-.504.054h-5.796c-.048.108-.072.306-.072.594 0 1.176.252 2.106.756 2.79.516.684 1.212 1.026 2.088 1.026.504 0 1.002-.114 1.494-.342.504-.228.99-.552 1.458-.972l.504.63zm-3.492-4.734c.48 0 .786-.024.918-.072.144-.06.216-.192.216-.396 0-.528-.15-.96-.45-1.296a1.455 1.455 0 0 0-1.134-.504c-.516 0-.978.216-1.386.648-.396.42-.654.96-.774 1.62h2.61zm8.945 3.618c0 .468.018.84.054 1.116.048.264.138.468.27.612.132.144.324.24.576.288.252.036.588.054 1.008.054V92h-6.012v-.72c.36-.024.648-.06.864-.108.216-.048.378-.144.486-.288.108-.144.174-.348.198-.612.036-.276.054-.642.054-1.098v-2.196c0-.744-.018-1.338-.054-1.782-.036-.444-.114-.786-.234-1.026a.867.867 0 0 0-.522-.468c-.216-.084-.504-.126-.864-.126v-.63l3.6-.666.288 2.07h.072c.324-.636.75-1.14 1.278-1.512.528-.372 1.086-.558 1.674-.558.456 0 .828.114 1.116.342.288.228.432.516.432.864 0 .384-.114.708-.342.972-.216.264-.516.396-.9.396-.18 0-.342-.036-.486-.108a3.131 3.131 0 0 1-.396-.234 2.28 2.28 0 0 0-.342-.252.549.549 0 0 0-.342-.126c-.228 0-.444.15-.648.45-.204.3-.372.702-.504 1.206a9.68 9.68 0 0 0-.234 1.224c-.06.444-.09.888-.09 1.332v.864zm6.139-4.428a5.587 5.587 0 0 0-.378-.828 1.667 1.667 0 0 0-.378-.486.847.847 0 0 0-.414-.234 2.18 2.18 0 0 0-.522-.054v-.72h5.382v.72c-.3 0-.54.012-.72.036-.168.024-.3.06-.396.108a.328.328 0 0 0-.162.198.798.798 0 0 0-.036.252c0 .156.03.336.09.54.06.204.132.408.216.612l1.71 4.716h.072l1.926-4.698a6.35 6.35 0 0 0 .198-.54 1.66 1.66 0 0 0 .072-.45c0-.264-.09-.456-.27-.576-.18-.12-.498-.186-.954-.198v-.72h3.978v.72c-.324 0-.606.084-.846.252-.228.168-.468.54-.72 1.116l-3.366 7.632h-1.638l-2.844-7.398zm14.041 4.266c0 .48.018.864.054 1.152.036.288.108.51.216.666a.833.833 0 0 0 .468.324c.204.048.48.078.828.09V92h-5.67v-.72c.336-.012.606-.048.81-.108a.968.968 0 0 0 .486-.324c.12-.156.198-.366.234-.63.048-.276.072-.624.072-1.044V86.96c0-.696-.012-1.266-.036-1.71-.024-.456-.054-.768-.09-.936-.06-.3-.198-.498-.414-.594-.204-.096-.582-.144-1.134-.144v-.612l4.176-.684v6.768zm-2.646-10.584c0-.396.132-.726.396-.99a1.35 1.35 0 0 1 .99-.414c.396 0 .726.138.99.414.276.264.414.594.414.99 0 .384-.138.714-.414.99a1.343 1.343 0 0 1-.99.396c-.384 0-.714-.132-.99-.396a1.382 1.382 0 0 1-.396-.99zm8.969 10.584c0 .48.018.864.054 1.152.036.288.108.51.216.666a.833.833 0 0 0 .468.324c.204.048.48.078.828.09V92h-5.67v-.72c.336-.012.606-.048.81-.108a.968.968 0 0 0 .486-.324c.12-.156.198-.366.234-.63.048-.276.072-.624.072-1.044V81.74c0-.696-.012-1.266-.036-1.71-.024-.456-.054-.768-.09-.936-.06-.3-.198-.498-.414-.594-.204-.096-.582-.144-1.134-.144v-.612l4.176-.684v11.988zm6.399 0c0 .48.018.864.054 1.152.036.288.108.51.216.666a.833.833 0 0 0 .468.324c.204.048.48.078.828.09V92h-5.67v-.72c.336-.012.606-.048.81-.108a.968.968 0 0 0 .486-.324c.12-.156.198-.366.234-.63.048-.276.072-.624.072-1.044V81.74c0-.696-.012-1.266-.036-1.71-.024-.456-.054-.768-.09-.936-.06-.3-.198-.498-.414-.594-.204-.096-.582-.144-1.134-.144v-.612l4.176-.684v11.988zm11.672 1.278c-1.092 1.236-2.454 1.854-4.086 1.854a5.787 5.787 0 0 1-2.034-.342c-.6-.24-1.116-.57-1.548-.99a4.592 4.592 0 0 1-1.008-1.53c-.24-.588-.36-1.242-.36-1.962 0-.744.126-1.422.378-2.034a4.619 4.619 0 0 1 1.062-1.602 5.01 5.01 0 0 1 1.638-1.062 5.62 5.62 0 0 1 2.088-.378c1.272 0 2.262.342 2.97 1.026.708.684 1.062 1.644 1.062 2.88 0 .192-.03.312-.09.36-.06.036-.228.054-.504.054h-5.796c-.048.108-.072.306-.072.594 0 1.176.252 2.106.756 2.79.516.684 1.212 1.026 2.088 1.026.504 0 1.002-.114 1.494-.342.504-.228.99-.552 1.458-.972l.504.63zm-3.492-4.734c.48 0 .786-.024.918-.072.144-.06.216-.192.216-.396 0-.528-.15-.96-.45-1.296a1.455 1.455 0 0 0-1.134-.504c-.516 0-.978.216-1.386.648-.396.42-.654.96-.774 1.62h2.61z",fill:"#FFF1E1"}));case"RUBIK_WORK":return Object(_.createElement)(z.SVG,{width:"232",height:"132",viewBox:"0 0 232 132",xmlns:"http://www.w3.org/2000/svg"},Object(_.createElement)(z.Path,{fill:"#000",d:"M0 0h232v132H0z"}),Object(_.createElement)(z.Path,{d:"M14.936 62c-.352 0-.656-.128-.912-.384a1.246 1.246 0 0 1-.384-.912V29.696c0-.352.128-.656.384-.912s.56-.384.912-.384h14.208c4.608 0 8.208 1.04 10.8 3.12 2.592 2.048 3.888 4.896 3.888 8.544 0 2.08-.464 3.92-1.392 5.52-.928 1.568-2.192 2.864-3.792 3.888l5.904 10.944c.096.192.144.368.144.528 0 .288-.112.544-.336.768a.977.977 0 0 1-.72.288H33.8c-.576 0-1.04-.128-1.392-.384-.32-.288-.544-.592-.672-.912l-4.128-9.168H25.64v9.168c0 .352-.128.656-.384.912s-.56.384-.912.384h-9.408zm14.208-19.584c.704 0 1.248-.224 1.632-.672.384-.48.576-1.072.576-1.776s-.192-1.312-.576-1.824c-.352-.544-.896-.816-1.632-.816H25.64v5.088h3.504zM56.873 62.48c-1.696 0-3.248-.384-4.656-1.152-1.408-.8-2.544-2.016-3.408-3.648-.832-1.632-1.248-3.664-1.248-6.096V38.336c0-.352.128-.656.384-.912s.56-.384.912-.384h9.168c.352 0 .656.128.912.384s.384.56.384.912v12.912c0 .864.208 1.52.624 1.968.416.448 1.008.672 1.776.672s1.36-.224 1.776-.672c.416-.448.624-1.104.624-1.968V38.336c0-.352.128-.656.384-.912s.56-.384.912-.384h9.12c.352 0 .656.128.912.384s.384.56.384.912v22.368c0 .352-.128.656-.384.912s-.56.384-.912.384h-8.4c-.352 0-.656-.128-.912-.384a1.246 1.246 0 0 1-.384-.912V59.12c-.768 1.12-1.84 1.968-3.216 2.544-1.376.544-2.96.816-4.752.816zm41.127 0c-3.04 0-5.408-.96-7.104-2.88v1.104c0 .352-.128.656-.384.912s-.56.384-.912.384h-8.16c-.352 0-.656-.128-.912-.384a1.246 1.246 0 0 1-.384-.912V29.216c0-.352.128-.656.384-.912s.56-.384.912-.384h8.88c.352 0 .656.128.912.384s.384.56.384.912v9.6C93.28 37.312 95.408 36.56 98 36.56c2.912 0 5.296.944 7.152 2.832 1.888 1.856 2.896 4.592 3.024 8.208.032.48.048 1.104.048 1.872 0 .8-.016 1.44-.048 1.92-.16 3.808-1.152 6.608-2.976 8.4-1.824 1.792-4.224 2.688-7.2 2.688zm-3.984-8.592c.832 0 1.408-.224 1.728-.672.352-.448.576-1.152.672-2.112.064-.64.096-1.168.096-1.584 0-.416-.032-.944-.096-1.584-.096-.96-.32-1.664-.672-2.112-.32-.448-.896-.672-1.728-.672-.8 0-1.392.208-1.776.624-.352.384-.56.976-.624 1.776-.032.48-.048 1.072-.048 1.776s.016 1.296.048 1.776c.064.928.272 1.632.624 2.112.352.448.944.672 1.776.672zM113.415 34.4c-.352 0-.656-.128-.912-.384a1.246 1.246 0 0 1-.384-.912v-5.808c0-.352.128-.656.384-.912s.56-.384.912-.384h8.112c.352 0 .656.128.912.384s.384.56.384.912v5.808c0 .352-.128.656-.384.912s-.56.384-.912.384h-8.112zm-.24 27.6c-.352 0-.656-.128-.912-.384a1.246 1.246 0 0 1-.384-.912V38.336c0-.352.128-.656.384-.912s.56-.384.912-.384h8.592c.352 0 .656.128.912.384s.384.56.384.912v22.368c0 .352-.128.656-.384.912s-.56.384-.912.384h-8.592zm15.515 0c-.352 0-.656-.128-.912-.384a1.246 1.246 0 0 1-.384-.912V29.216c0-.352.128-.656.384-.912s.56-.384.912-.384h8.4c.352 0 .656.128.912.384s.384.56.384.912v15.552l4.224-6.912c.32-.544.784-.816 1.392-.816h9.696c.32 0 .592.112.816.336.224.224.336.496.336.816 0 .224-.08.464-.24.72l-6.576 9.36 7.776 11.952c.128.192.192.4.192.624 0 .32-.112.592-.336.816a1.11 1.11 0 0 1-.816.336h-10.08c-.64 0-1.136-.272-1.488-.816l-4.896-8.16v7.68c0 .352-.128.656-.384.912s-.56.384-.912.384h-8.4zM25.4 105.48c-3.776 0-6.768-.88-8.976-2.64-2.208-1.76-3.312-4.16-3.312-7.2 0-1.952.56-3.664 1.68-5.136 1.12-1.472 2.72-2.8 4.8-3.984-1.216-1.312-2.096-2.528-2.64-3.648-.512-1.152-.768-2.32-.768-3.504 0-1.536.4-2.944 1.2-4.224.8-1.28 1.984-2.304 3.552-3.072 1.568-.768 3.456-1.152 5.664-1.152 2.048 0 3.824.384 5.328 1.152 1.536.736 2.688 1.744 3.456 3.024a7.494 7.494 0 0 1 1.2 4.128c0 1.856-.56 3.456-1.68 4.8-1.12 1.312-2.784 2.608-4.992 3.888l5.712 5.712c.512-.832.944-1.632 1.296-2.4.384-.8.768-1.84 1.152-3.12.128-.448.464-.672 1.008-.672h4.848c.256 0 .48.096.672.288.192.16.288.368.288.624-.032 1.12-.56 2.64-1.584 4.56-.992 1.92-2.096 3.616-3.312 5.088l5.376 5.424c.224.288.336.528.336.72a.774.774 0 0 1-.288.624.844.844 0 0 1-.624.24h-6.528c-.512 0-.928-.16-1.248-.48l-2.16-2.064c-2.464 2.016-5.616 3.024-9.456 3.024zm.432-21.984c1.28-.64 2.24-1.264 2.88-1.872.672-.608 1.008-1.328 1.008-2.16 0-.864-.304-1.552-.912-2.064-.576-.544-1.312-.816-2.208-.816a3.31 3.31 0 0 0-2.208.816c-.608.544-.912 1.248-.912 2.112 0 .576.176 1.184.528 1.824.384.608.992 1.328 1.824 2.16zM25.4 99.384c1.984 0 3.632-.592 4.944-1.776l-6.384-6.384c-2.112 1.12-3.168 2.48-3.168 4.08 0 1.216.464 2.208 1.392 2.976.928.736 2 1.104 3.216 1.104zM65.56 105h-3.168l-6.24-21.12h2.752l5.088 19.104 4.992-19.104h2.912l4.992 19.168 5.12-19.168H84.6L78.392 105h-3.168L71.48 91.304l-1.088-4.768h-.032l-1.088 4.768L65.56 105zm28.824-16.32c2.41 0 4.299.736 5.664 2.208 1.387 1.472 2.08 3.51 2.08 6.112 0 2.603-.693 4.64-2.08 6.112-1.365 1.472-3.253 2.208-5.664 2.208-2.41 0-4.31-.736-5.696-2.208-1.365-1.472-2.048-3.51-2.048-6.112 0-2.603.683-4.64 2.048-6.112 1.387-1.472 3.286-2.208 5.696-2.208zm0 2.208c-1.621 0-2.89.544-3.808 1.632C89.66 93.608 89.2 95.101 89.2 97c0 1.899.459 3.392 1.376 4.48.918 1.088 2.187 1.632 3.808 1.632 1.622 0 2.89-.544 3.808-1.632.918-1.088 1.376-2.581 1.376-4.48 0-1.899-.458-3.392-1.376-4.48-.917-1.088-2.186-1.632-3.808-1.632zm20.269-2.208c.768 0 1.355.107 1.76.32l-.512 2.496c-.512-.277-1.184-.416-2.016-.416-.683 0-1.355.203-2.016.608-.64.384-1.173.981-1.6 1.792-.405.79-.608 1.75-.608 2.88V105h-2.56V89h2.08l.352 2.624c.896-1.963 2.603-2.944 5.12-2.944zm11.463 8.416l-3.392 3.392V105h-2.56V81.64h2.56v15.648L131.012 89h3.2l-6.24 6.24 6.624 9.76h-3.104l-5.376-7.904zm29.655-13.536c3.776 0 6.496 1.493 8.16 4.48l-2.208 1.792c-.64-1.408-1.408-2.4-2.304-2.976-.874-.597-2.08-.896-3.616-.896-1.621 0-2.901.341-3.84 1.024-.917.661-1.376 1.515-1.376 2.56 0 .683.182 1.248.544 1.696.363.448.96.843 1.792 1.184.854.32 2.027.608 3.52.864 2.795.47 4.768 1.173 5.92 2.112 1.174.939 1.76 2.24 1.76 3.904 0 1.195-.341 2.251-1.024 3.168-.661.896-1.61 1.6-2.848 2.112-1.237.491-2.666.736-4.288.736-2.133 0-3.957-.416-5.472-1.248-1.493-.832-2.634-1.941-3.424-3.328l2.208-1.792c.576 1.259 1.419 2.24 2.528 2.944 1.131.683 2.539 1.024 4.224 1.024 1.664 0 2.987-.299 3.968-.896.982-.619 1.472-1.483 1.472-2.592 0-.939-.426-1.685-1.28-2.24-.853-.555-2.368-1.024-4.544-1.408-2.816-.49-4.81-1.195-5.984-2.112-1.173-.917-1.76-2.197-1.76-3.84 0-1.13.32-2.176.96-3.136.64-.96 1.558-1.717 2.752-2.272 1.195-.576 2.582-.864 4.16-.864zm26.044 19.584a5.25 5.25 0 0 0 1.28-.16l-.16 2.016a5.68 5.68 0 0 1-1.92.32c-.832 0-1.494-.181-1.984-.544-.47-.363-.768-.971-.896-1.824-.491.747-1.216 1.333-2.176 1.76a7.435 7.435 0 0 1-2.976.608c-1.579 0-2.88-.363-3.904-1.088-1.024-.747-1.536-1.813-1.536-3.2 0-1.216.533-2.261 1.6-3.136 1.066-.896 2.613-1.515 4.64-1.856l4.256-.704v-.896c0-1.067-.331-1.92-.992-2.56-.662-.64-1.579-.96-2.752-.96-1.067 0-1.995.256-2.784.768-.768.512-1.366 1.27-1.792 2.272l-1.888-1.376c.426-1.195 1.216-2.144 2.368-2.848 1.173-.704 2.538-1.056 4.096-1.056 1.898 0 3.424.459 4.576 1.376 1.152.917 1.728 2.272 1.728 4.064v7.872c0 .384.096.672.288.864.192.192.501.288.928.288zm-8.704-.064c1.344 0 2.496-.32 3.456-.96.981-.64 1.472-1.472 1.472-2.496v-2.208l-3.584.672c-1.43.256-2.496.63-3.2 1.12-.704.47-1.056 1.077-1.056 1.824 0 .661.256 1.173.768 1.536.512.341 1.226.512 2.144.512zm21.485-14.4c1.813 0 3.306.523 4.48 1.568 1.173 1.045 1.76 2.55 1.76 4.512V105h-2.56v-9.344c0-1.664-.363-2.87-1.088-3.616-.704-.747-1.654-1.12-2.848-1.12-.854 0-1.654.192-2.4.576-.747.363-1.366.97-1.856 1.824-.47.832-.704 1.888-.704 3.168V105h-2.56V89h2.24l.16 2.496c.533-.96 1.269-1.664 2.208-2.112.938-.47 1.994-.704 3.168-.704zm17.476 16.64c-1.536 0-2.922-.299-4.16-.896-1.237-.619-2.144-1.525-2.72-2.72l2.08-1.44a3.898 3.898 0 0 0 1.888 2.112c.896.469 1.952.704 3.168.704 1.259 0 2.219-.224 2.88-.672.662-.448.992-1.013.992-1.696 0-.619-.309-1.11-.928-1.472-.618-.384-1.706-.715-3.264-.992-1.536-.277-2.752-.608-3.648-.992-.896-.405-1.546-.907-1.952-1.504-.405-.619-.608-1.376-.608-2.272 0-.875.256-1.675.768-2.4.512-.725 1.248-1.301 2.208-1.728.96-.448 2.07-.672 3.328-.672 1.707 0 3.072.32 4.096.96 1.046.619 1.792 1.579 2.24 2.88l-2.176 1.28c-.341-1.024-.864-1.76-1.568-2.208-.682-.448-1.546-.672-2.592-.672-1.045 0-1.93.235-2.656.704-.725.47-1.088 1.013-1.088 1.632 0 .704.31 1.248.928 1.632.64.384 1.771.715 3.392.992 2.219.363 3.787.907 4.704 1.632.918.725 1.376 1.75 1.376 3.072a3.95 3.95 0 0 1-.832 2.464c-.533.704-1.312 1.259-2.336 1.664-1.002.405-2.176.608-3.52.608z",fill:"#fff"}));case"PLAY_ROBOTO":return Object(_.createElement)(z.SVG,{width:"232",height:"132",viewBox:"0 0 232 132",xmlns:"http://www.w3.org/2000/svg"},Object(_.createElement)(z.Path,{fill:"#B9B5B8",d:"M0 0h232v132H0z"}),Object(_.createElement)(z.Path,{d:"M149.438 101c-.75-2.125-1.23-5.27-1.438-9.438-2.625 3.417-5.979 6.063-10.062 7.938-4.042 1.833-8.334 2.75-12.876 2.75-6.5 0-11.77-1.812-15.812-5.438-4-3.624-6-8.208-6-13.75 0-6.583 2.729-11.791 8.188-15.624 5.5-3.834 13.145-5.75 22.937-5.75h13.563V54c0-4.833-1.5-8.625-4.5-11.375-2.959-2.792-7.292-4.188-13-4.188-5.209 0-9.521 1.334-12.938 4-3.417 2.667-5.125 5.876-5.125 9.626l-7.5-.063c0-5.375 2.5-10.02 7.5-13.938 5-3.958 11.146-5.937 18.437-5.937 7.542 0 13.48 1.896 17.813 5.688 4.375 3.75 6.625 9 6.75 15.75v32c0 6.541.687 11.437 2.063 14.687v.75h-8zm-23.5-5.375c5 0 9.458-1.208 13.374-3.625 3.959-2.417 6.834-5.646 8.626-9.688V67.439h-13.376c-7.458.083-13.291 1.458-17.5 4.124-4.208 2.626-6.312 6.25-6.312 10.876 0 3.791 1.396 6.937 4.188 9.437 2.833 2.5 6.5 3.75 11 3.75zM39.328 101.896c-5.461 0-9.6-1.451-12.416-4.352-2.73-2.987-4.096-6.699-4.096-11.136 0-3.84.981-6.997 2.944-9.472 2.048-2.56 4.437-4.523 7.168-5.888 2.73-1.365 6.272-2.773 10.624-4.224 4.608-1.536 7.979-2.944 10.112-4.224 2.133-1.28 3.2-3.072 3.2-5.376V45.832c0-2.73-.683-5.163-2.048-7.296s-3.712-3.2-7.04-3.2c-2.645 0-5.035.725-7.168 2.176 2.901 1.024 5.035 2.56 6.4 4.608 1.45 1.963 2.176 4.181 2.176 6.656 0 3.328-1.195 6.016-3.584 8.064-2.304 1.963-5.12 2.944-8.448 2.944-3.328 0-5.973-1.024-7.936-3.072-1.877-2.133-2.816-4.821-2.816-8.064 0-2.56.64-4.779 1.92-6.656 1.28-1.877 3.285-3.584 6.016-5.12 4.779-2.73 11.605-4.096 20.48-4.096 4.693 0 8.747.47 12.16 1.408 3.413.853 6.315 2.517 8.704 4.992 1.707 1.792 2.816 4.053 3.328 6.784.597 2.645.896 6.357.896 11.136V91.4c0 2.133.128 3.584.384 4.352.341.768.896 1.152 1.664 1.152.597 0 1.237-.17 1.92-.512a15.863 15.863 0 0 0 1.92-1.408l1.28 2.176c-3.67 3.157-8.917 4.736-15.744 4.736-5.12 0-8.704-.853-10.752-2.56-2.048-1.792-3.157-4.181-3.328-7.168-4.01 6.485-9.984 9.728-17.92 9.728zm12.8-10.24c1.792 0 3.37-.725 4.736-2.176V62.472c-.768 1.28-2.176 2.944-4.224 4.992-2.304 2.219-4.053 4.395-5.248 6.528-1.195 2.048-1.792 4.864-1.792 8.448 0 6.144 2.176 9.216 6.528 9.216z",fill:"#270920"}));default:return Object(_.createElement)("div",{className:"font-pairings-panel__preview"},Object(_.createElement)("h1",{style:{fontFamily:t}},"Lorem Ipsum"),Object(_.createElement)("p",{style:{fontFamily:c}},"Etiam tempor orci eu lobortis elementum nibh tellus molestie."))}},B=function(e){var t=e.fontPairings,c=e.fontBase,n=e.fontHeadings,a=e.update;return Object(_.createElement)(_.Fragment,null,Object(_.createElement)("h3",null,Object(y.__)("Font Pairings")),t&&n&&c?Object(_.createElement)("div",{role:"listbox"},t.map((function(e){var t=e.label,r=e.headings,l=e.base,o=e.preview,s=r===n&&l===c,i=V()("font-pairings-panel",{"is-selected":s});return Object(_.createElement)("div",{key:t,tabIndex:0,role:"option","aria-selected":s,className:i,onClick:function(){return a({headings:r,base:l})},onKeyDown:function(e){return e.keyCode===P.ENTER?a({headings:r,base:l}):null}},Object(_.createElement)("div",{className:"font-pairings-panel__preview"},H(o,r,l)),Object(_.createElement)("p",{className:"font-pairings-panel__label"},t))}))):Object(_.createElement)(S,{unsupportedFeature:Object(y.__)("font pairings")}))},M=function(e){var t=e.fontBase,c=e.fontBaseDefault,n=e.fontHeadings,a=e.fontHeadingsDefault,r=e.fontBaseOptions,l=e.fontHeadingsOptions,o=e.updateBaseFont,s=e.updateHeadingsFont;return r&&l?Object(_.createElement)(_.Fragment,null,Object(_.createElement)(z.SelectControl,{label:Object(y.__)("Heading Font"),value:n,options:l,onChange:function(e){return s(e)},style:{fontFamily:"unset"!==n?n:a}}),Object(_.createElement)(z.SelectControl,{label:Object(y.__)("Base Font"),value:t,options:r,onChange:function(e){return o(e)},style:{fontFamily:"unset"!==t?t:c}}),Object(_.createElement)("hr",null)):Object(_.createElement)(S,{unsupportedFeature:Object(y.__)("custom font selection")})},x=function(){return Object(_.createElement)(z.SVG,{xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24"},Object(_.createElement)(z.Path,{d:"M9.93 13.5h4.14L12 7.98zM20 2H4c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-4.05 16.5l-1.14-3H9.17l-1.12 3H5.96l5.11-13h1.86l5.11 13h-2.09z"}))},T=function(e){if("object"==typeof e){var t=e.label,c=e.value,n=e.prop;return{label:t,value:c,prop:void 0===n?"ANY_PROPERTY":n}}return{label:e,value:e,prop:"ANY_PROPERTY"}},N=function(e){return null!==e.value&&null!==e.label},L=function(e,t){return e?e.map(T).filter(N).filter(function(e){return function(t){return"ANY_PROPERTY"===t.prop||t.prop===e}}(t)):[]},C=function(e){var t=e.hasLocalChanges,c=e.resetAction,n=e.publishAction,a=e.className,r=void 0===a?null:a;return Object(_.createElement)("div",{className:r},Object(_.createElement)(z.Button,{disabled:!t,isDefault:!0,onClick:c},Object(y.__)("Reset")),Object(_.createElement)(z.Button,{className:"global-styles-sidebar__publish-button",disabled:!t,isPrimary:!0,onClick:n},Object(y.__)("Publish")))},F=(c(13),JETPACK_GLOBAL_STYLES_EDITOR_CONSTANTS),A=F.PLUGIN_NAME,I=F.STORE_NAME,R=F.REST_PATH;n=I,a=R,Object(s.registerStore)(n,{reducer:function(e,t){switch(t.type){case"UPDATE_OPTIONS":case"RESET_OPTIONS":case"PUBLISH_OPTIONS":return h()({},e,{},t.options)}return e},actions:O,selectors:{getOption:function(e,t){return e?e[t]:void 0},hasLocalChanges:function(e){return!!e&&Object.keys(v).some((function(t){return v[t]!==e[t]}))}},resolvers:{getOption:regeneratorRuntime.mark((function e(t){var c;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(!b){e.next=2;break}return e.abrupt("return");case 2:return e.prev=2,b=!0,e.next=6,O.fetchOptions();case 6:c=e.sent,e.next=12;break;case 9:e.prev=9,e.t0=e.catch(2),c={};case 12:return v=c,e.abrupt("return",{type:"UPDATE_OPTIONS",options:c});case 14:case"end":return e.stop()}}),e,null,[[2,9]])}))},controls:{IO_FETCH_OPTIONS:function(){return p()({path:a})},IO_PUBLISH_OPTIONS:function(e){var t=e.options;return v=t,p()({path:a,method:"POST",data:h()({},t)})}}}),r=["font_base","font_headings"],l=Object(s.select)(I).getOption,d()((function(){var e={},t={};r.forEach((function(c){e[c]=null,t[c]="--".concat(c.replace("_","-"))})),Object(s.subscribe)((function(){Object.keys(e).forEach((function(c){var n=l(c);if(e[c]!==n){e[c]=n;var a=document.getElementsByClassName("editor-styles-wrapper")[0];a&&a.style.setProperty(t[c],n)}}))}))})),Object(o.registerPlugin)(A,{render:Object(i.compose)(Object(s.withSelect)((function(e){return{siteName:e(I).getOption("blogname"),fontHeadings:e(I).getOption("font_headings"),fontHeadingsDefault:e(I).getOption("font_headings_default"),fontBase:e(I).getOption("font_base"),fontBaseDefault:e(I).getOption("font_base_default"),fontPairings:e(I).getOption("font_pairings"),fontOptions:e(I).getOption("font_options"),hasLocalChanges:e(I).hasLocalChanges()}})),Object(s.withDispatch)((function(e){return{updateOptions:e(I).updateOptions,publishOptions:e(I).publishOptions,resetLocalChanges:e(I).resetLocalChanges}})))((function(e){var t=e.fontHeadings,c=e.fontHeadingsDefault,n=e.fontBase,a=e.fontBaseDefault,r=e.fontPairings,l=e.fontOptions,o=e.siteName,s=e.publishOptions,i=e.updateOptions,u=e.hasLocalChanges,h=e.resetLocalChanges,f=function(){var e;return s((e={},j()(e,"font_base",n),j()(e,"font_headings",t),e))};return Object(_.createElement)(_.Fragment,null,Object(_.createElement)(E.PluginSidebarMoreMenuItem,{icon:Object(_.createElement)(x,null),target:"global-styles"},Object(y.__)("Global Styles")),Object(_.createElement)(E.PluginSidebar,{icon:Object(_.createElement)(x,null),name:"global-styles",title:Object(y.__)("Global Styles"),className:"global-styles-sidebar"},Object(_.createElement)(z.PanelBody,null,Object(_.createElement)("p",null,Object(y.sprintf)(Object(y.__)("You are customizing %s."),o)),Object(_.createElement)("p",null,Object(y.__)("Any change you make here will apply to the entire website.")),u?Object(_.createElement)("div",null,Object(_.createElement)("p",null,Object(_.createElement)("em",null,Object(y.__)("You have unsaved changes."))),Object(_.createElement)(C,{hasLocalChanges:u,publishAction:f,resetAction:h})):null),Object(_.createElement)(z.PanelBody,{title:Object(y.__)("Font Selection")},Object(_.createElement)(M,{fontBase:n,fontBaseDefault:a,fontHeadings:t,fontHeadingsDefault:c,fontBaseOptions:L(l,"font_base"),fontHeadingsOptions:L(l,"font_headings"),updateBaseFont:function(e){return i(j()({},"font_base",e))},updateHeadingsFont:function(e){return i(j()({},"font_headings",e))}}),Object(_.createElement)(B,{fontHeadings:t,fontBase:n,fontPairings:r,update:function(e){var t,c=e.headings,n=e.base;return i((t={},j()(t,"font_headings",c),j()(t,"font_base",n),t))}})),Object(_.createElement)(z.PanelBody,null,u?Object(_.createElement)("p",null,Object(_.createElement)("em",null,Object(y.__)("You have unsaved changes."))):null,Object(_.createElement)(C,{hasLocalChanges:u,publishAction:f,resetAction:h,className:"global-styles-sidebar__panel-action-buttons"}))))}))})}]));
 
 
trunk/global-styles/dist/global-styles.js.LICENSE DELETED
@@ -1,5 +0,0 @@
1
- /*!
2
- Copyright (c) 2017 Jed Watson.
3
- Licensed under the MIT License (MIT), see
4
- http://jedwatson.github.io/classnames
5
- */
 
 
 
 
 
trunk/global-styles/dist/global-styles.rtl.css DELETED
@@ -1 +0,0 @@
1
- .global-styles-sidebar .components-select-control__input{line-height:1;font-size:18px;height:36px}.global-styles-sidebar h3{margin:0 0 1em}.global-styles-sidebar__panel-action-buttons{display:flex;justify-content:flex-end;margin-bottom:96px}.global-styles-sidebar__publish-button{margin-right:1em}.font-pairings-panel{cursor:pointer;border-radius:4px;padding:4px;margin-bottom:.5em}.font-pairings-panel.is-selected{box-shadow:0 0 0 2px #555d66}.font-pairings-panel:focus{box-shadow:0 0 0 2px #00a0d2}.font-pairings-panel:hover{background-color:#f3f4f5;color:#191e23}.font-pairings-panel__preview{border:1px solid rgba(25,30,35,.2);border-radius:4px;background-color:#fff;padding:4px}.font-pairings-panel__preview h1,.font-pairings-panel__preview p{margin:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding:10px 0}.font-pairings-panel__preview svg{display:block;width:100%;height:auto}.font-pairings-panel__label{text-align:center;margin-bottom:0}
 
trunk/global-styles/editor.scss DELETED
@@ -1,2 +0,0 @@
1
- @import './src/global-styles-sidebar.scss';
2
- @import './src/font-pairings-panel.scss';
 
 
trunk/global-styles/includes/class-data-point-literal.php DELETED
@@ -1,44 +0,0 @@
1
- <?php
2
- /**
3
- * Class Data Point Literal.
4
- *
5
- * @package Automattic\Jetpack\Global_Styles
6
- */
7
-
8
- namespace Automattic\Jetpack\Global_Styles;
9
-
10
- require_once __DIR__ . '/interface-data-point.php';
11
-
12
- /**
13
- * Literal Data Point.
14
- */
15
- class Data_Point_Literal implements Data_Point {
16
-
17
- /**
18
- * Holds the literal value.
19
- *
20
- * @var any
21
- */
22
- private $value;
23
-
24
- /**
25
- * Constructor.
26
- *
27
- * @param any $meta Data point description.
28
- */
29
- public function __construct( $meta ) {
30
- if ( array_key_exists( 'default', $meta ) ) {
31
- $this->value = $meta['default'];
32
- }
33
- }
34
-
35
- /**
36
- * Implements \Automattic\Jetpack\Global_Styles\Data_Point interface.
37
- *
38
- * @return any The literal value.
39
- */
40
- public function get_value() {
41
- return $this->value;
42
- }
43
-
44
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/global-styles/includes/class-data-point-option.php DELETED
@@ -1,104 +0,0 @@
1
- <?php
2
- /**
3
- * Class Data Point Option.
4
- *
5
- * @package Automattic\Jetpack\Global_Styles
6
- */
7
-
8
- namespace Automattic\Jetpack\Global_Styles;
9
-
10
- require_once __DIR__ . '/interface-data-point.php';
11
-
12
- /**
13
- * Option Data Point.
14
- */
15
- class Data_Point_Option implements Data_Point {
16
-
17
- /**
18
- * Option name.
19
- *
20
- * @var string
21
- */
22
- private $option_name;
23
-
24
- /**
25
- * Option property to access, if exist.
26
- *
27
- * @var string
28
- */
29
- private $option_property;
30
-
31
- /**
32
- * Default option value.
33
- *
34
- * @var any
35
- */
36
- private $default_value;
37
-
38
- /**
39
- * Constructor.
40
- *
41
- * @param array $meta Data point description.
42
- */
43
- public function __construct( $meta ) {
44
- if ( is_array( $meta['name'] ) ) {
45
- $this->option_name = $meta['name'][0];
46
- $this->option_property = $meta['name'][1];
47
- } else {
48
- $this->option_name = $meta['name'];
49
- }
50
-
51
- if ( array_key_exists( 'default', $meta ) ) {
52
- $this->default_value = $meta['default'];
53
- } else {
54
- $this->default_value = false;
55
- }
56
- }
57
-
58
- /**
59
- * Implements \Automattic\Jetpack\Global_Styles\Data_Point interface.
60
- *
61
- * @return any The value to return.
62
- */
63
- public function get_value() {
64
- if ( ! isset( $this->option_property ) ) {
65
- return get_option( $this->option_name, $this->default_value );
66
- }
67
-
68
- $value = get_option( $this->option_name, [] );
69
- if ( is_array( $value ) && array_key_exists( $this->option_property, $value ) ) {
70
- return $value[ $this->option_property ];
71
- }
72
-
73
- return $this->default_value;
74
- }
75
-
76
- /**
77
- * Return the option name this data point belongs to.
78
- *
79
- * @return string Option name
80
- */
81
- public function get_option_name() {
82
- return $this->option_name;
83
- }
84
-
85
- /**
86
- * Process new data.
87
- *
88
- * @param any $current_option_value Current option value.
89
- * @param any $new_value Value to update.
90
- * @return any The modified option value.
91
- */
92
- public function process_data_point( $current_option_value, $new_value ) {
93
- $result = $current_option_value;
94
-
95
- if ( isset( $this->option_property ) ) {
96
- $result[ $this->option_property ] = $new_value;
97
- } else {
98
- $result = $new_value;
99
- }
100
-
101
- return $result;
102
- }
103
-
104
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/global-styles/includes/class-data-point-theme.php DELETED
@@ -1,92 +0,0 @@
1
- <?php
2
- /**
3
- * Class Data Point Theme.
4
- *
5
- * @package Automattic\Jetpack\Global_Styles
6
- */
7
-
8
- namespace Automattic\Jetpack\Global_Styles;
9
-
10
- require_once __DIR__ . '/interface-data-point.php';
11
-
12
- /**
13
- * Theme Data Point.
14
- */
15
- class Data_Point_Theme implements Data_Point {
16
-
17
- /**
18
- * Feature name.
19
- *
20
- * @var string
21
- */
22
- private $feature_name;
23
-
24
- /**
25
- * Option property to access, if exists.
26
- *
27
- * @var string
28
- */
29
- private $feature_property;
30
-
31
- /**
32
- * Default value to return if no found.
33
- *
34
- * @var string
35
- */
36
- private $default_value;
37
-
38
- /**
39
- * Constructor.
40
- *
41
- * @param array $meta Data point description.
42
- */
43
- public function __construct( $meta ) {
44
- if ( is_array( $meta['name'] ) ) {
45
- $this->feature_name = $meta['name'][0];
46
- $this->feature_property = $meta['name'][1];
47
- } else {
48
- $this->feature_name = $meta['name'];
49
- }
50
-
51
- if ( array_key_exists( 'default', $meta ) ) {
52
- $this->default_value = $meta['default'];
53
- }
54
- }
55
-
56
- /**
57
- * Implements the \Automattic\Jetpack\Global_Styles\Data_Point interface.
58
- */
59
- public function get_value() {
60
- $theme_support = get_theme_support( $this->feature_name )[0];
61
-
62
- if ( false === $theme_support || true === $theme_support ) {
63
- return $this->default_value;
64
- }
65
-
66
- if (
67
- is_array( $theme_support ) &&
68
- ! isset( $this->feature_property )
69
- ) {
70
- return $theme_support;
71
- }
72
-
73
- if (
74
- is_array( $theme_support ) &&
75
- isset( $this->feature_property ) &&
76
- array_key_exists( $this->feature_property, $theme_support )
77
- ) {
78
- return $theme_support[ $this->feature_property ];
79
- }
80
-
81
- if (
82
- is_array( $theme_support ) &&
83
- isset( $this->feature_property ) &&
84
- ! array_key_exists( $this->feature_property, $theme_support )
85
- ) {
86
- return $this->default_value;
87
- }
88
-
89
- return $this->default_value;
90
- }
91
-
92
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/global-styles/includes/class-data-set.php DELETED
@@ -1,167 +0,0 @@
1
- <?php
2
- /**
3
- * Class Data Set.
4
- *
5
- * @package Automattic\Jetpack\Global_Styles
6
- */
7
-
8
- namespace Automattic\Jetpack\Global_Styles;
9
-
10
- /**
11
- * Utility to retrieve data from a description.
12
- */
13
- class Data_Set {
14
-
15
- /**
16
- * Description of the data points to work with.
17
- *
18
- * @var array
19
- */
20
- private $data_meta = [];
21
-
22
- /**
23
- * Set of objects that implement the Data_Point interface.
24
- *
25
- * @var array
26
- */
27
- private $data_set = [];
28
-
29
- /**
30
- * Constructor
31
- *
32
- * @param array $data_meta Description of the data points to work with.
33
- */
34
- public function __construct( $data_meta ) {
35
- $this->data_meta = $data_meta;
36
- $this->data_set = $this->build_data_set( $data_meta );
37
- }
38
-
39
- /**
40
- * Build data set from the meta data provided.
41
- *
42
- * @param array $data_meta Meta data description.
43
- * @return array The data set structure.
44
- */
45
- private function build_data_set( $data_meta ) {
46
- require_once __DIR__ . '/class-data-point-literal.php';
47
- require_once __DIR__ . '/class-data-point-option.php';
48
- require_once __DIR__ . '/class-data-point-theme.php';
49
-
50
- $result = [];
51
- foreach ( $data_meta as $key => $meta ) {
52
- if ( $this->is_data_point_literal( $meta ) ) {
53
- $result[ $key ] = new Data_Point_Literal( $meta );
54
- } elseif ( $this->is_data_point_option( $meta ) ) {
55
- $result[ $key ] = new Data_Point_Option( $meta );
56
- } elseif ( $this->is_data_point_theme( $meta ) ) {
57
- $result[ $key ] = new Data_Point_Theme( $meta );
58
- }
59
- }
60
- return $result;
61
- }
62
-
63
- /**
64
- * Whether the description provided is a data point
65
- * whose value should be taken literally.
66
- *
67
- * @param array $meta Data point description.
68
- * @return boolean
69
- */
70
- private function is_data_point_literal( $meta ) {
71
- return array_key_exists( 'type', $meta ) && 'literal' === $meta['type'];
72
- }
73
-
74
- /**
75
- * Whether the description provided is a data point
76
- * whose value should be taken from an option.
77
- *
78
- * @param array $meta Data point description.
79
- * @return boolean
80
- */
81
- private function is_data_point_option( $meta ) {
82
- return array_key_exists( 'type', $meta ) &&
83
- 'option' === $meta['type'] &&
84
- array_key_exists( 'name', $meta );
85
- }
86
-
87
- /**
88
- * Whether the description provided is a data point
89
- * that can be updated.
90
- *
91
- * @param array $meta Data point description.
92
- * @return boolean
93
- */
94
- private function is_data_point_updatable( $meta ) {
95
- return $this->is_data_point_option( $meta ) &&
96
- array_key_exists( 'updatable', $meta ) &&
97
- $meta['updatable'];
98
- }
99
-
100
- /**
101
- * Whether the description provided is a data point
102
- * whose value should be taken from theme support.
103
- *
104
- * @param array $meta Data point description.
105
- * @return boolean
106
- */
107
- private function is_data_point_theme( $meta ) {
108
- return array_key_exists( 'name', $meta ) &&
109
- array_key_exists( 'type', $meta ) &&
110
- 'theme' === $meta['type'];
111
- }
112
-
113
- /**
114
- * Process the data description given and return the values.
115
- *
116
- * @return array Values.
117
- */
118
- public function get_data() {
119
- $result = [];
120
- foreach ( $this->data_set as $key => $data_point ) {
121
- $result[ $key ] = $data_point->get_value();
122
- }
123
-
124
- $result = apply_filters( 'jetpack_global_styles_data_set_get_data', $result );
125
-
126
- return $result;
127
- }
128
-
129
- /**
130
- * Process incoming data.
131
- *
132
- * @param array $incoming_data Incoming data.
133
- */
134
- public function save_data( $incoming_data ) {
135
- $to_update = [];
136
-
137
- $incoming_data = apply_filters( 'jetpack_global_styles_data_set_save_data', $incoming_data );
138
-
139
- $options_updatable = array_filter(
140
- $this->data_meta,
141
- [ $this, 'is_data_point_updatable' ]
142
- );
143
- foreach ( $options_updatable as $key => $meta ) {
144
- $option_name = $this->data_set[ $key ]->get_option_name();
145
-
146
- // Get current value, if we haven't yet.
147
- if ( ! array_key_exists( $option_name, $to_update ) ) {
148
- $to_update[ $option_name ] = get_option( $option_name );
149
- }
150
-
151
- // Override with incoming value, if appropiate.
152
- // At this point it should have been validated, sanitized, etc.
153
- if ( array_key_exists( $key, $incoming_data ) ) {
154
- $to_update[ $option_name ] = $this->data_set[ $key ]->process_data_point( $to_update[ $option_name ], $incoming_data[ $key ] );
155
- }
156
- }
157
-
158
- $did_update = false;
159
- foreach ( $to_update as $key => $value ) {
160
- if ( update_option( $key, $value ) ) {
161
- $did_update = true;
162
- }
163
- }
164
-
165
- return $did_update;
166
- }
167
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/global-styles/includes/class-json-endpoint.php DELETED
@@ -1,116 +0,0 @@
1
- <?php
2
- /**
3
- * JSON REST API endpoint for Global Styles plugin.
4
- *
5
- * @package Automattic\Jetpack\Global_Styles
6
- */
7
-
8
- namespace Automattic\Jetpack\Global_Styles;
9
-
10
- /**
11
- * REST API endpoint for Global Styles plugin.
12
- */
13
- class JSON_Endpoint extends \WP_REST_Controller {
14
-
15
- /**
16
- * Namespace for the REST endpoint.
17
- *
18
- * @var string
19
- */
20
- private $rest_namespace;
21
-
22
- /**
23
- * Route name for the REST endpoint.
24
- *
25
- * @var string
26
- */
27
- private $rest_route;
28
-
29
- /**
30
- * Object holding the data description to work with.
31
- *
32
- * @var Automattic\Jetpack\Global_Styles\Data_Set
33
- */
34
- private $data_set;
35
-
36
- /**
37
- * Permission check callback.
38
- *
39
- * @var callable
40
- */
41
- private $permission_cb;
42
-
43
- /**
44
- * Constructor
45
- *
46
- * @param string $rest_namespace Namespace for the REST endpoint.
47
- * @param string $rest_route Route name.
48
- * @param array $data_set Description of the data to work with.
49
- * @param callable $permission_cb Permission check callback.
50
- */
51
- public function __construct( $rest_namespace, $rest_route, $data_set, $permission_cb ) {
52
- $this->rest_namespace = $rest_namespace;
53
- $this->rest_route = $rest_route;
54
- $this->data_set = $data_set;
55
- $this->permission_cb = $permission_cb;
56
- }
57
-
58
- /**
59
- * Callback to determine whether the request can proceed.
60
- *
61
- * @return boolean
62
- */
63
- public function permission_callback() {
64
- return call_user_func( $this->permission_cb );
65
- }
66
-
67
- /**
68
- * Initialize the routes. To be called on `rest_api_init'
69
- *
70
- * @return void
71
- */
72
- public function setup() {
73
- register_rest_route(
74
- $this->rest_namespace,
75
- $this->rest_route,
76
- [
77
- [
78
- 'methods' => \WP_REST_Server::READABLE,
79
- 'callback' => [ $this, 'get_data' ],
80
- 'permission_callback' => [ $this, 'permission_callback' ],
81
- ],
82
- ]
83
- );
84
- register_rest_route(
85
- $this->rest_namespace,
86
- $this->rest_route,
87
- [
88
- [
89
- 'methods' => \WP_REST_Server::CREATABLE,
90
- 'callback' => [ $this, 'update_data' ],
91
- 'permission_callback' => [ $this, 'permission_callback' ],
92
- ],
93
- ]
94
- );
95
- }
96
-
97
- /**
98
- * Process the incoming request to get data.
99
- *
100
- * @return Array
101
- */
102
- public function get_data() {
103
- return $this->data_set->get_data();
104
- }
105
-
106
- /**
107
- * Process the incoming request to update data.
108
- *
109
- * @param \WP_REST_Request $request Incoming request.
110
- * @return Boolean False if data hasn't changed or update failed, true otherwise.
111
- */
112
- public function update_data( \WP_REST_Request $request ) {
113
- $incoming_data = $request->get_json_params();
114
- return $this->data_set->save_data( $incoming_data );
115
- }
116
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/global-styles/includes/interface-data-point.php DELETED
@@ -1,17 +0,0 @@
1
- <?php
2
- /**
3
- * Interface Data Point.
4
- *
5
- * @package Automattic\Jetpack\Global_Styles
6
- */
7
-
8
- namespace Automattic\Jetpack\Global_Styles;
9
-
10
- interface Data_Point {
11
- /**
12
- * Return value of the data point.
13
- *
14
- * @return any
15
- */
16
- public function get_value();
17
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/global-styles/index.js DELETED
@@ -1,51 +0,0 @@
1
- /**
2
- * External dependencies
3
- */
4
- import { registerPlugin } from '@wordpress/plugins';
5
- import { withDispatch, withSelect, select } from '@wordpress/data';
6
- import { compose } from '@wordpress/compose';
7
-
8
- /**
9
- * Internal dependencies
10
- */
11
- import registerStore from './src/store';
12
- import registerDOMUpdater from './src/dom-updater';
13
- import GlobalStylesSidebar from './src/global-styles-sidebar';
14
- import {
15
- FONT_BASE,
16
- FONT_BASE_DEFAULT,
17
- FONT_HEADINGS,
18
- FONT_HEADINGS_DEFAULT,
19
- FONT_PAIRINGS,
20
- FONT_OPTIONS,
21
- SITE_NAME,
22
- } from './src/constants';
23
-
24
- // Tell Webpack to compile this into CSS
25
- import './editor.scss';
26
-
27
- // Global variable.
28
- const { PLUGIN_NAME, STORE_NAME, REST_PATH } = JETPACK_GLOBAL_STYLES_EDITOR_CONSTANTS; // eslint-disable-line no-undef
29
-
30
- registerStore( STORE_NAME, REST_PATH );
31
- registerDOMUpdater( [ FONT_BASE, FONT_HEADINGS ], select( STORE_NAME ).getOption );
32
-
33
- registerPlugin( PLUGIN_NAME, {
34
- render: compose(
35
- withSelect( getSelectors => ( {
36
- siteName: getSelectors( STORE_NAME ).getOption( SITE_NAME ),
37
- fontHeadings: getSelectors( STORE_NAME ).getOption( FONT_HEADINGS ),
38
- fontHeadingsDefault: getSelectors( STORE_NAME ).getOption( FONT_HEADINGS_DEFAULT ),
39
- fontBase: getSelectors( STORE_NAME ).getOption( FONT_BASE ),
40
- fontBaseDefault: getSelectors( STORE_NAME ).getOption( FONT_BASE_DEFAULT ),
41
- fontPairings: getSelectors( STORE_NAME ).getOption( FONT_PAIRINGS ),
42
- fontOptions: getSelectors( STORE_NAME ).getOption( FONT_OPTIONS ),
43
- hasLocalChanges: getSelectors( STORE_NAME ).hasLocalChanges(),
44
- } ) ),
45
- withDispatch( dispatch => ( {
46
- updateOptions: dispatch( STORE_NAME ).updateOptions,
47
- publishOptions: dispatch( STORE_NAME ).publishOptions,
48
- resetLocalChanges: dispatch( STORE_NAME ).resetLocalChanges,
49
- } ) )
50
- )( GlobalStylesSidebar ),
51
- } );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/global-styles/src/constants.js DELETED
@@ -1,7 +0,0 @@
1
- export const FONT_BASE = 'font_base';
2
- export const FONT_BASE_DEFAULT = 'font_base_default';
3
- export const FONT_HEADINGS = 'font_headings';
4
- export const FONT_HEADINGS_DEFAULT = 'font_headings_default';
5
- export const FONT_PAIRINGS = 'font_pairings';
6
- export const FONT_OPTIONS = 'font_options';
7
- export const SITE_NAME = 'blogname';
 
 
 
 
 
 
 
trunk/global-styles/src/dom-updater.js DELETED
@@ -1,36 +0,0 @@
1
- /**
2
- * External dependencies
3
- */
4
- import { subscribe } from '@wordpress/data';
5
- import domReady from '@wordpress/dom-ready';
6
-
7
- /**
8
- * DOM updater
9
- *
10
- * @param {string[]} options A list of option names to keep track of.
11
- * @param {Function} getOptionValue A function that given an option name as a string, returns the current option value.
12
- */
13
- export default ( options, getOptionValue ) => {
14
- domReady( () => {
15
- const current = {};
16
- const cssVariables = {};
17
- options.forEach( option => {
18
- current[ option ] = null;
19
- cssVariables[ option ] = `--${ option.replace( '_', '-' ) }`;
20
- } );
21
-
22
- subscribe( () => {
23
- Object.keys( current ).forEach( key => {
24
- const value = getOptionValue( key );
25
- if ( current[ key ] !== value ) {
26
- current[ key ] = value;
27
- // We want to scope this to the root node of the editor.
28
- const node = document.getElementsByClassName( 'editor-styles-wrapper' )[ 0 ];
29
- if ( node ) {
30
- node.style.setProperty( cssVariables[ key ], value );
31
- }
32
- }
33
- } );
34
- } );
35
- } );
36
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/global-styles/src/font-pairings-panel-previews.js DELETED
@@ -1,73 +0,0 @@
1
- /**
2
- * External dependencies
3
- */
4
- import { Path, SVG } from '@wordpress/components';
5
-
6
- const SpaceLora = () => (
7
- <SVG width="232" height="132" viewBox="0 0 232 132" xmlns="http://www.w3.org/2000/svg">
8
- <Path fill="#fa4d4b" d="M0 0h232v132H0z" />
9
- <Path
10
- d="M24.1 62c-3.6-2.9-8.9-5-15.8-6.3-2.8-.5-5-1-6.9-1.6-.5-.2-1-.3-1.5-.5v12.5c1.4.3 2.9.6 4.4.9 2.5.4 4.6 1 6.2 1.6s2.9 1.3 3.9 2.2c.9.8 1.6 1.6 2 2.6.4.9.6 1.9.6 3 0 2.3-.9 4.2-2.7 5.8-1.8 1.6-4.6 2.4-8.4 2.4-2.2 0-4.2-.3-5.9-.8v12c1.8.3 3.7.4 5.7.4 3.7 0 7-.5 10-1.4 2.9-.9 5.5-2.3 7.5-4s3.6-3.9 4.7-6.3c1.1-2.5 1.7-5.3 1.7-8.4V75c0-5.7-1.8-10-5.5-13zM12.9 42.5c2.1 1.9 3.1 4.2 3.1 6.9v2.3h12.4v-3.4c0-2.7-.5-5.3-1.6-7.7-1-2.4-2.5-4.6-4.6-6.5-2-1.9-4.5-3.4-7.5-4.4-3-1.1-6.5-1.7-10.3-1.7-1.5 0-3 .1-4.4.3v11.9c1.3-.4 2.7-.5 4.4-.5 3.7-.2 6.5.8 8.5 2.8zm67.9 10.9c-1.8-2.1-4-3.6-6.5-4.7-2.4-1.1-5-1.6-7.8-1.6-3.7 0-6.7.7-9.1 2.2-2.4 1.4-4.2 3.4-5.5 5.9h-1.7v-6.8H38.4v65.4h11.8V88.2H52c.6 1.1 1.2 2.1 2 3.1.8.9 1.8 1.8 2.9 2.5 1.2.8 2.6 1.3 4.1 1.8 1.6.4 3.4.7 5.5.7 2.9 0 5.5-.5 8-1.5 2.5-1.1 4.7-2.6 6.5-4.6 1.8-2.1 3.3-4.6 4.3-7.5 1.1-2.9 1.6-6.3 1.6-10.2v-1.7c0-3.8-.6-7.1-1.7-10.1-1-2.9-2.5-5.3-4.4-7.3zm-5.7 18.9c0 3.9-1.2 7.1-3.5 9.4-2.3 2.3-5.2 3.4-8.9 3.4s-6.7-1.2-9-3.5c-2.3-2.4-3.4-5.5-3.4-9.3v-1.1c0-3.8 1.1-6.9 3.4-9.2 2.3-2.4 5.3-3.6 9-3.6s6.7 1.2 8.9 3.5c2.3 2.3 3.5 5.4 3.5 9.3v1.1zm66.2 8.6V48.4h-11.8V54h-1.7c-1.2-2.4-2.8-4.1-4.9-5.3-2-1.1-4.7-1.7-8-1.7-2.8 0-5.4.6-7.8 1.7-2.4 1.1-4.5 2.6-6.3 4.7-1.8 2.1-3.3 4.6-4.3 7.6-1.1 2.9-1.6 6.3-1.6 10v1.5c0 3.8.5 7.1 1.6 10.1 1.1 2.9 2.6 5.5 4.5 7.5 1.9 2.1 4 3.6 6.5 4.7s5.2 1.6 8 1.6c3 0 5.6-.6 7.9-1.8 2.3-1.3 4-3.4 5.3-6.3h1.7c0 2 .7 3.6 2 4.9 1.4 1.3 3.1 1.9 5.3 1.9h8.1V83.7H144c-1.8 0-2.7-.9-2.7-2.8zm-11.8-8.6c0 3.9-1 7.1-3.1 9.4-2.1 2.3-4.8 3.4-8.3 3.4-3.4 0-6.2-1.1-8.3-3.4-2.1-2.3-3.1-5.5-3.1-9.4v-1.1c0-3.9 1-7.1 3.1-9.3 2.1-2.3 4.8-3.5 8.3-3.5 3.4 0 6.2 1.2 8.3 3.5 2.1 2.3 3.1 5.4 3.1 9.3v1.1zm98.3-12.2c1.2-1 2.6-1.6 4.2-2V47.3c-2.1.3-4 .8-5.9 1.6-2.8 1.1-5.3 2.7-7.4 4.8-2.1 2.1-3.8 4.6-5.1 7.5-1.2 2.9-1.8 6.2-1.8 9.8v.6c0 3.9.6 7.4 1.7 10.4 1.2 3.1 2.8 5.7 4.9 7.8 2.1 2.1 4.6 3.8 7.5 4.9 1.9.7 4 1.2 6.1 1.5V84.7c-.4-.1-.7-.2-1.1-.3-1.3-.5-2.5-1.2-3.6-2-1-.9-1.8-1.9-2.4-3-.6-1.2-.9-2.5-.9-3.9h8V65.4h-7.8c.5-2 1.8-3.8 3.6-5.3zm-61.5 6.1c.7-1.7 1.6-3.1 2.7-4.2 1.1-1.2 2.4-2.1 3.9-2.7 1.5-.6 3.1-.9 4.8-.9 3.6 0 6.5 1 8.5 3s3.2 4.4 3.6 7.1l11.7-3c-1.1-5.5-3.6-10-7.7-13.3-4-3.4-9.3-5.1-15.8-5.1-3.4 0-6.6.6-9.6 1.7-2.9 1.1-5.5 2.8-7.8 4.9-2.2 2.1-3.9 4.7-5.2 7.7s-1.9 6.4-1.9 10.2v1.1c0 3.8.6 7.1 1.9 10.1 1.3 2.9 3 5.4 5.2 7.4s4.8 3.5 7.7 4.6c3 1.1 6.2 1.6 9.7 1.6 6.6 0 11.9-1.7 15.9-5.1 4-3.4 6.5-7.8 7.6-13.3l-11.7-3c-.6 3.1-1.8 5.5-3.8 7.3-1.9 1.8-4.6 2.7-8.3 2.7-1.7 0-3.3-.3-4.8-.8-1.5-.6-2.8-1.4-3.9-2.4-1.1-1.1-2-2.4-2.7-3.9-.6-1.6-.9-3.5-.9-5.5v-.6c0-2.1.3-3.9.9-5.6z"
11
- fill="#270920"
12
- />
13
- <Path
14
- d="M49.7 89.3c-1.1 1.3-2.6 2-4.5 2h-6.5c.1-1.1.2-2.5.2-4.3V68.5c0-1.3.1-2.2.4-2.8s.6-1 1.1-1.1c.5-.2 1.1-.3 2-.3v-3.2h-14v3.7l3.6-.1c-.1 1.1-.2 2.5-.2 4.4v18.5c0 1.3-.1 2.2-.4 2.8-.3.6-.6 1-1.1 1.2-.5.2-1.1.3-2 .3V95h25.8l.3-11.6h-3.2c.1 2.6-.5 4.5-1.5 5.9zM101.3 70c-2.5 0-4.8 1.5-7 4.5h-.1v-2.3c0-.8-.1-1.4-.1-1.9h-2.4c-.4.4-1.3.7-2.5 1-1.3.3-2.9.4-4.9.4v3.7l3.4-.1c-.1 1.3-.2 2.7-.2 4.1v8.1c0 1.5-.2 2.6-.5 3.3-.3.7-1.1 1-2.3 1V95h12.7v-3.7c-1.1 0-2.1 0-3.1.1.1-1.3.2-2.7.2-4.3v-7.9c.3-1 1-2.1 1.9-3.1 1-1.1 1.9-1.6 2.8-1.6.1 1 .5 1.8 1.1 2.2.6.4 1.4.6 2.2.6 1.1 0 1.9-.4 2.5-1.1.5-.7.8-1.5.8-2.3 0-1.3-.4-2.3-1.2-3-1-.5-2-.9-3.3-.9zm25.8 21.5c.1-1.3.2-2.7.2-4.3v-7.9c0-6.2-3-9.2-9-9.2-1.9 0-3.6.3-5.2.8-1.5.5-2.8 1.3-3.7 2.2-.9 1-1.4 2.1-1.4 3.3 0 .9.3 1.7.8 2.4.5.6 1.3.9 2.3.9 1 0 1.8-.3 2.3-.9.5-.6.8-1.3.8-2.1s-.2-1.4-.6-1.8c.9-.9 2.1-1.4 3.5-1.4 2.2 0 3.3 1.5 3.3 4.4v2.5c-3.7.2-6.9 1-9.5 2.5-2.6 1.5-4 3.6-4 6.4 0 1.9.6 3.4 1.7 4.6 1.2 1.2 2.8 1.8 4.8 1.8 2.8 0 5.2-1 7.2-3 .1 1.1.1 1.8.2 2.2h9.1v-3.7c-.7.1-1.8.2-2.8.3zm-6.6-2.2c-1.1 1.2-2.4 1.7-3.8 1.7-.8 0-1.4-.2-2-.6-.5-.4-.8-1.1-.8-1.9 0-1.3.6-2.4 1.8-3.1 1.3-.8 2.8-1.3 4.7-1.5v5.4zM75.1 71.5c-1.8-1-3.9-1.5-6.2-1.5-2.2 0-4.3.6-6.1 1.7-1.8 1.1-3.3 2.7-4.4 4.7-1.1 2-1.6 4.4-1.6 7 0 2.5.5 4.7 1.6 6.5 1.1 1.9 2.5 3.3 4.4 4.3 1.9 1 4 1.5 6.3 1.5 2.4 0 4.4-.5 6.2-1.6 1.8-1.1 3.3-2.6 4.3-4.6 1-2 1.5-4.3 1.5-7 0-2.5-.5-4.7-1.6-6.6-1.1-1.9-2.5-3.4-4.4-4.4zm-2.2 18.4c-.7 1.6-2 2.5-3.7 2.5-1.8 0-3.1-1-4-3-.9-2-1.3-4.4-1.3-7.2 0-2.5.4-4.5 1.2-6.2.8-1.7 2.1-2.5 3.9-2.5 1.7 0 3 1 3.8 3s1.2 4.4 1.2 7.2c-.1 2.5-.4 4.5-1.1 6.2z"
15
- fill="#fff"
16
- />
17
- </SVG>
18
- );
19
-
20
- const SystemBasker = () => (
21
- <SVG width="232" height="132" viewBox="0 0 232 132" xmlns="http://www.w3.org/2000/svg">
22
- <Path fill="#F18F1B" d="M0 0h232v132H0z" />
23
- <Path
24
- d="M10.016 50.563c.14 4.25 3.718 6.828 9.093 6.828 5.641 0 9.094-2.797 9.094-7.203 0-3.422-2.078-5.344-6.844-6.297l-2.39-.485c-2.657-.531-3.75-1.39-3.75-2.781 0-1.656 1.562-2.75 3.89-2.75 2.375 0 4.047 1.156 4.203 3.078h4.454c-.078-4.14-3.391-6.89-8.657-6.89-5.015 0-8.609 2.734-8.609 6.859 0 3.36 2.203 5.516 6.703 6.406l2.375.469c2.828.578 3.89 1.422 3.89 2.906 0 1.656-1.718 2.875-4.234 2.875-2.562 0-4.468-1.125-4.765-3.016h-4.453zM53 37v-8.422l7.86-14.125h-5.063l-5.063 9.625h-.109l-5.047-9.625h-5.14l7.843 14.125V37H53zM73.016 60.563c.14 4.25 3.718 6.828 9.093 6.828 5.641 0 9.094-2.797 9.094-7.204 0-3.421-2.078-5.343-6.844-6.296l-2.39-.485c-2.656-.531-3.75-1.39-3.75-2.781 0-1.656 1.562-2.75 3.89-2.75 2.375 0 4.047 1.156 4.204 3.078h4.453c-.079-4.14-3.391-6.89-8.657-6.89-5.015 0-8.609 2.734-8.609 6.859 0 3.36 2.203 5.516 6.703 6.406l2.375.469c2.828.578 3.89 1.422 3.89 2.906 0 1.656-1.718 2.875-4.234 2.875-2.562 0-4.468-1.125-4.765-3.016h-4.453zM114.984 47V28.344h6.532v-3.89H103.75v3.89h6.516V47h4.718zM149.812 43.094h-10.218v-5.688h9.64v-3.625h-9.64v-5.437h10.218v-3.89h-14.937V47h14.937v-3.906zM187.75 37V14.453h-5.469l-6.406 16.188h-.125l-6.406-16.188h-5.469V37h4.203V21.781h.125L174.328 37h2.969l6.125-15.219h.125V37h4.203z"
25
- fill="#492B06"
26
- />
27
- <Path
28
- d="M22.032 92H9.63v-.72c.396-.012.72-.048.972-.108s.444-.162.576-.306c.132-.144.222-.348.27-.612.048-.264.072-.606.072-1.026v-8.316c0-.42-.024-.756-.072-1.008-.036-.264-.114-.468-.234-.612a.852.852 0 0 0-.522-.306 4.454 4.454 0 0 0-.864-.126v-.72h6.21v.72a5.062 5.062 0 0 0-.99.108c-.24.06-.426.168-.558.324-.132.156-.222.372-.27.648a8.868 8.868 0 0 0-.054 1.098v7.542c0 .504.048.918.144 1.242.108.312.288.558.54.738.252.168.588.288 1.008.36.42.06.942.09 1.566.09.696 0 1.278-.042 1.746-.126.468-.084.858-.24 1.17-.468.324-.24.582-.558.774-.954.192-.396.354-.912.486-1.548h.72L22.032 92zm5.182-2.952c0 .48.018.864.054 1.152.036.288.108.51.216.666a.833.833 0 0 0 .468.324c.204.048.48.078.828.09V92h-5.67v-.72c.336-.012.606-.048.81-.108a.968.968 0 0 0 .486-.324c.12-.156.198-.366.234-.63.048-.276.072-.624.072-1.044V86.96c0-.696-.012-1.266-.036-1.71-.024-.456-.054-.768-.09-.936-.06-.3-.198-.498-.414-.594-.204-.096-.582-.144-1.134-.144v-.612l4.176-.684v6.768zm-2.646-10.584c0-.396.132-.726.396-.99a1.35 1.35 0 0 1 .99-.414c.396 0 .726.138.99.414.276.264.414.594.414.99 0 .384-.138.714-.414.99a1.343 1.343 0 0 1-.99.396c-.384 0-.714-.132-.99-.396a1.382 1.382 0 0 1-.396-.99zm8.574 9.594c0 .444.06.858.18 1.242.132.372.306.696.522.972.216.276.474.492.774.648.3.156.63.234.99.234.72 0 1.266-.33 1.638-.99.372-.66.558-1.632.558-2.916 0-1.248-.186-2.196-.558-2.844-.36-.66-.906-.99-1.638-.99-.432 0-.834.12-1.206.36-.36.228-.642.552-.846.972-.276.576-.414 1.302-.414 2.178v1.134zm-.036-4.356h.072a3.07 3.07 0 0 1 1.206-1.044c.492-.252 1.05-.378 1.674-.378.636 0 1.224.132 1.764.396.552.252 1.026.6 1.422 1.044.408.444.726.966.954 1.566.228.6.342 1.242.342 1.926 0 .72-.126 1.386-.378 1.998-.24.6-.576 1.122-1.008 1.566-.42.444-.918.792-1.494 1.044a4.362 4.362 0 0 1-1.8.378c-.66 0-1.284-.126-1.872-.378-.576-.264-1.038-.606-1.386-1.026L31.234 92h-.612V81.29c0-1.128-.078-1.902-.234-2.322a.93.93 0 0 0-.126-.216.488.488 0 0 0-.216-.144 1.07 1.07 0 0 0-.36-.108 7.62 7.62 0 0 0-.612-.108v-.612l4.032-.72v6.642zm12.759 5.508c0 .468.018.84.054 1.116.048.264.138.468.27.612.132.144.324.24.576.288.252.036.588.054 1.008.054V92H41.76v-.72c.36-.024.648-.06.864-.108.216-.048.378-.144.486-.288.108-.144.174-.348.198-.612.036-.276.054-.642.054-1.098v-2.196c0-.744-.018-1.338-.054-1.782-.036-.444-.114-.786-.234-1.026a.867.867 0 0 0-.522-.468c-.216-.084-.504-.126-.864-.126v-.63l3.6-.666.288 2.07h.072c.324-.636.75-1.14 1.278-1.512.528-.372 1.086-.558 1.674-.558.456 0 .828.114 1.116.342.288.228.432.516.432.864 0 .384-.114.708-.342.972-.216.264-.516.396-.9.396-.18 0-.342-.036-.486-.108a3.131 3.131 0 0 1-.396-.234 2.28 2.28 0 0 0-.342-.252.549.549 0 0 0-.342-.126c-.228 0-.444.15-.648.45-.204.3-.372.702-.504 1.206a9.68 9.68 0 0 0-.234 1.224c-.06.444-.09.888-.09 1.332v.864zM59.8 90.326c-1.092 1.236-2.454 1.854-4.086 1.854a5.787 5.787 0 0 1-2.034-.342c-.6-.24-1.116-.57-1.548-.99a4.592 4.592 0 0 1-1.008-1.53c-.24-.588-.36-1.242-.36-1.962 0-.744.126-1.422.378-2.034a4.619 4.619 0 0 1 1.062-1.602 5.01 5.01 0 0 1 1.638-1.062 5.62 5.62 0 0 1 2.088-.378c1.272 0 2.262.342 2.97 1.026.708.684 1.062 1.644 1.062 2.88 0 .192-.03.312-.09.36-.06.036-.228.054-.504.054h-5.796c-.048.108-.072.306-.072.594 0 1.176.252 2.106.756 2.79.516.684 1.212 1.026 2.088 1.026.504 0 1.002-.114 1.494-.342.504-.228.99-.552 1.458-.972l.504.63zm-3.492-4.734c.48 0 .786-.024.918-.072.144-.06.216-.192.216-.396 0-.528-.15-.96-.45-1.296a1.455 1.455 0 0 0-1.134-.504c-.516 0-.978.216-1.386.648-.396.42-.654.96-.774 1.62h2.61zM65.985 92v-.72a4.75 4.75 0 0 0 .972-.108c.252-.06.444-.162.576-.306.144-.144.24-.348.288-.612.048-.264.072-.606.072-1.026v-8.316c0-.42-.018-.756-.054-1.008-.036-.264-.114-.468-.234-.612a.755.755 0 0 0-.468-.306 3.572 3.572 0 0 0-.774-.126v-.72h5.778c1.812 0 3.204.294 4.176.882.984.576 1.476 1.404 1.476 2.484 0 1.428-1.026 2.436-3.078 3.024v.072c.66 0 1.254.096 1.782.288.54.18.996.438 1.368.774a3.523 3.523 0 0 1 1.17 2.682c0 .612-.15 1.146-.45 1.602-.288.456-.708.84-1.26 1.152-1.068.6-2.538.9-4.41.9h-6.93zm7.056-1.098c1.932 0 2.898-.87 2.898-2.61 0-1.068-.348-1.848-1.044-2.34-.36-.252-.828-.432-1.404-.54-.564-.108-1.26-.162-2.088-.162h-.864v3.6c0 .744.192 1.272.576 1.584.384.312 1.026.468 1.926.468zM71.6 84.17c.54 0 1.008-.048 1.404-.144a3.249 3.249 0 0 0 1.008-.45c.576-.396.864-1.014.864-1.854 0-.876-.216-1.506-.648-1.89-.432-.396-1.128-.594-2.088-.594h-1.278c-.216 0-.324.102-.324.306v4.626H71.6zm14.325 2.7c-1.008.456-1.77.882-2.286 1.278-.504.384-.756.786-.756 1.206 0 .348.096.624.288.828a.948.948 0 0 0 .72.306c.288 0 .558-.048.81-.144.252-.108.468-.246.648-.414.18-.168.318-.366.414-.594.108-.24.162-.492.162-.756v-1.71zm0-.954v-.756c0-.696-.126-1.2-.378-1.512-.24-.324-.618-.486-1.134-.486-.348 0-.612.096-.792.288-.18.18-.348.486-.504.918-.108.3-.264.534-.468.702-.192.168-.462.252-.81.252-.336 0-.594-.102-.774-.306-.18-.204-.27-.492-.27-.864 0-.576.312-1.032.936-1.368.636-.336 1.59-.504 2.862-.504 1.344 0 2.304.246 2.88.738.576.48.864 1.29.864 2.43v3.942c0 1.02.204 1.53.612 1.53a.978.978 0 0 0 .63-.234l.27.522c-.168.3-.432.54-.792.72a2.7 2.7 0 0 1-1.188.252c-.552 0-.972-.168-1.26-.504-.288-.336-.432-.81-.432-1.422h-.09c-.348.624-.798 1.098-1.35 1.422-.552.324-1.182.486-1.89.486-.756 0-1.362-.21-1.818-.63-.456-.432-.684-.99-.684-1.674 0-.528.234-1.02.702-1.476.468-.468 1.248-.924 2.34-1.368l2.538-1.098zM91.6 92h-.558v-3.276h.756c.204.864.498 1.494.882 1.89.384.396.882.594 1.494.594.444 0 .786-.09 1.026-.27a.923.923 0 0 0 .378-.774c0-.336-.15-.66-.45-.972-.3-.324-.786-.666-1.458-1.026-.912-.492-1.566-.978-1.962-1.458a2.574 2.574 0 0 1-.594-1.656c0-.396.072-.762.216-1.098.156-.348.36-.648.612-.9.264-.252.576-.444.936-.576.36-.144.75-.216 1.17-.216.372 0 .738.054 1.098.162.372.108.696.258.972.45l.324-.432h.468v2.718h-.702c-.276-.684-.564-1.176-.864-1.476-.288-.3-.642-.45-1.062-.45-.336 0-.606.09-.81.27-.192.18-.288.42-.288.72 0 .336.144.654.432.954.3.3.792.63 1.476.99.48.264.894.522 1.242.774s.63.51.846.774c.216.252.372.522.468.81.108.276.162.576.162.9 0 .42-.078.798-.234 1.134a2.462 2.462 0 0 1-.666.864c-.288.24-.636.426-1.044.558-.396.132-.84.198-1.332.198-.516 0-.996-.066-1.44-.198-.444-.144-.81-.348-1.098-.612L91.6 92zm13.299-.72c.384 0 .654-.012.81-.036.156-.036.234-.102.234-.198 0-.072-.084-.246-.252-.522-.156-.288-.36-.618-.612-.99l-1.368-2.052-.9.864v.702c0 .468.018.846.054 1.134.036.288.096.516.18.684a.759.759 0 0 0 .378.324c.168.06.378.09.63.09V92h-5.31v-.72c.336-.012.606-.048.81-.108a.969.969 0 0 0 .486-.306c.12-.156.198-.366.234-.63a6.4 6.4 0 0 0 .072-1.062v-7.632c0-.732-.012-1.308-.036-1.728-.024-.42-.09-.732-.198-.936a.647.647 0 0 0-.468-.396 3.877 3.877 0 0 0-.846-.072v-.666l4.014-.684v10.008l1.728-1.638a28.697 28.697 0 0 0 1.332-1.314c.264-.3.396-.516.396-.648 0-.108-.114-.18-.342-.216-.216-.048-.624-.072-1.224-.072v-.72h4.914v.72c-.456 0-.858.078-1.206.234-.348.156-.726.426-1.134.81l-1.746 1.638 3.114 4.41c.276.384.546.648.81.792.264.144.612.216 1.044.216V92h-5.598v-.72zm14.737-.954c-1.092 1.236-2.454 1.854-4.086 1.854a5.787 5.787 0 0 1-2.034-.342c-.6-.24-1.116-.57-1.548-.99a4.592 4.592 0 0 1-1.008-1.53c-.24-.588-.36-1.242-.36-1.962 0-.744.126-1.422.378-2.034a4.619 4.619 0 0 1 1.062-1.602 5.01 5.01 0 0 1 1.638-1.062 5.62 5.62 0 0 1 2.088-.378c1.272 0 2.262.342 2.97 1.026.708.684 1.062 1.644 1.062 2.88 0 .192-.03.312-.09.36-.06.036-.228.054-.504.054h-5.796c-.048.108-.072.306-.072.594 0 1.176.252 2.106.756 2.79.516.684 1.212 1.026 2.088 1.026.504 0 1.002-.114 1.494-.342.504-.228.99-.552 1.458-.972l.504.63zm-3.492-4.734c.48 0 .786-.024.918-.072.144-.06.216-.192.216-.396 0-.528-.15-.96-.45-1.296a1.455 1.455 0 0 0-1.134-.504c-.516 0-.978.216-1.386.648-.396.42-.654.96-.774 1.62h2.61zm8.945 3.618c0 .468.018.84.054 1.116.048.264.138.468.27.612.132.144.324.24.576.288.252.036.588.054 1.008.054V92h-6.012v-.72c.36-.024.648-.06.864-.108.216-.048.378-.144.486-.288.108-.144.174-.348.198-.612.036-.276.054-.642.054-1.098v-2.196c0-.744-.018-1.338-.054-1.782-.036-.444-.114-.786-.234-1.026a.867.867 0 0 0-.522-.468c-.216-.084-.504-.126-.864-.126v-.63l3.6-.666.288 2.07h.072c.324-.636.75-1.14 1.278-1.512.528-.372 1.086-.558 1.674-.558.456 0 .828.114 1.116.342.288.228.432.516.432.864 0 .384-.114.708-.342.972-.216.264-.516.396-.9.396-.18 0-.342-.036-.486-.108a3.131 3.131 0 0 1-.396-.234 2.28 2.28 0 0 0-.342-.252.549.549 0 0 0-.342-.126c-.228 0-.444.15-.648.45-.204.3-.372.702-.504 1.206a9.68 9.68 0 0 0-.234 1.224c-.06.444-.09.888-.09 1.332v.864zm6.139-4.428a5.587 5.587 0 0 0-.378-.828 1.667 1.667 0 0 0-.378-.486.847.847 0 0 0-.414-.234 2.18 2.18 0 0 0-.522-.054v-.72h5.382v.72c-.3 0-.54.012-.72.036-.168.024-.3.06-.396.108a.328.328 0 0 0-.162.198.798.798 0 0 0-.036.252c0 .156.03.336.09.54.06.204.132.408.216.612l1.71 4.716h.072l1.926-4.698a6.35 6.35 0 0 0 .198-.54 1.66 1.66 0 0 0 .072-.45c0-.264-.09-.456-.27-.576-.18-.12-.498-.186-.954-.198v-.72h3.978v.72c-.324 0-.606.084-.846.252-.228.168-.468.54-.72 1.116l-3.366 7.632h-1.638l-2.844-7.398zm14.041 4.266c0 .48.018.864.054 1.152.036.288.108.51.216.666a.833.833 0 0 0 .468.324c.204.048.48.078.828.09V92h-5.67v-.72c.336-.012.606-.048.81-.108a.968.968 0 0 0 .486-.324c.12-.156.198-.366.234-.63.048-.276.072-.624.072-1.044V86.96c0-.696-.012-1.266-.036-1.71-.024-.456-.054-.768-.09-.936-.06-.3-.198-.498-.414-.594-.204-.096-.582-.144-1.134-.144v-.612l4.176-.684v6.768zm-2.646-10.584c0-.396.132-.726.396-.99a1.35 1.35 0 0 1 .99-.414c.396 0 .726.138.99.414.276.264.414.594.414.99 0 .384-.138.714-.414.99a1.343 1.343 0 0 1-.99.396c-.384 0-.714-.132-.99-.396a1.382 1.382 0 0 1-.396-.99zm8.969 10.584c0 .48.018.864.054 1.152.036.288.108.51.216.666a.833.833 0 0 0 .468.324c.204.048.48.078.828.09V92h-5.67v-.72c.336-.012.606-.048.81-.108a.968.968 0 0 0 .486-.324c.12-.156.198-.366.234-.63.048-.276.072-.624.072-1.044V81.74c0-.696-.012-1.266-.036-1.71-.024-.456-.054-.768-.09-.936-.06-.3-.198-.498-.414-.594-.204-.096-.582-.144-1.134-.144v-.612l4.176-.684v11.988zm6.399 0c0 .48.018.864.054 1.152.036.288.108.51.216.666a.833.833 0 0 0 .468.324c.204.048.48.078.828.09V92h-5.67v-.72c.336-.012.606-.048.81-.108a.968.968 0 0 0 .486-.324c.12-.156.198-.366.234-.63.048-.276.072-.624.072-1.044V81.74c0-.696-.012-1.266-.036-1.71-.024-.456-.054-.768-.09-.936-.06-.3-.198-.498-.414-.594-.204-.096-.582-.144-1.134-.144v-.612l4.176-.684v11.988zm11.672 1.278c-1.092 1.236-2.454 1.854-4.086 1.854a5.787 5.787 0 0 1-2.034-.342c-.6-.24-1.116-.57-1.548-.99a4.592 4.592 0 0 1-1.008-1.53c-.24-.588-.36-1.242-.36-1.962 0-.744.126-1.422.378-2.034a4.619 4.619 0 0 1 1.062-1.602 5.01 5.01 0 0 1 1.638-1.062 5.62 5.62 0 0 1 2.088-.378c1.272 0 2.262.342 2.97 1.026.708.684 1.062 1.644 1.062 2.88 0 .192-.03.312-.09.36-.06.036-.228.054-.504.054h-5.796c-.048.108-.072.306-.072.594 0 1.176.252 2.106.756 2.79.516.684 1.212 1.026 2.088 1.026.504 0 1.002-.114 1.494-.342.504-.228.99-.552 1.458-.972l.504.63zm-3.492-4.734c.48 0 .786-.024.918-.072.144-.06.216-.192.216-.396 0-.528-.15-.96-.45-1.296a1.455 1.455 0 0 0-1.134-.504c-.516 0-.978.216-1.386.648-.396.42-.654.96-.774 1.62h2.61z"
29
- fill="#FFF1E1"
30
- />
31
- </SVG>
32
- );
33
-
34
- const RubikWork = () => (
35
- <SVG width="232" height="132" viewBox="0 0 232 132" xmlns="http://www.w3.org/2000/svg">
36
- <Path fill="#000" d="M0 0h232v132H0z" />
37
- <Path
38
- d="M14.936 62c-.352 0-.656-.128-.912-.384a1.246 1.246 0 0 1-.384-.912V29.696c0-.352.128-.656.384-.912s.56-.384.912-.384h14.208c4.608 0 8.208 1.04 10.8 3.12 2.592 2.048 3.888 4.896 3.888 8.544 0 2.08-.464 3.92-1.392 5.52-.928 1.568-2.192 2.864-3.792 3.888l5.904 10.944c.096.192.144.368.144.528 0 .288-.112.544-.336.768a.977.977 0 0 1-.72.288H33.8c-.576 0-1.04-.128-1.392-.384-.32-.288-.544-.592-.672-.912l-4.128-9.168H25.64v9.168c0 .352-.128.656-.384.912s-.56.384-.912.384h-9.408zm14.208-19.584c.704 0 1.248-.224 1.632-.672.384-.48.576-1.072.576-1.776s-.192-1.312-.576-1.824c-.352-.544-.896-.816-1.632-.816H25.64v5.088h3.504zM56.873 62.48c-1.696 0-3.248-.384-4.656-1.152-1.408-.8-2.544-2.016-3.408-3.648-.832-1.632-1.248-3.664-1.248-6.096V38.336c0-.352.128-.656.384-.912s.56-.384.912-.384h9.168c.352 0 .656.128.912.384s.384.56.384.912v12.912c0 .864.208 1.52.624 1.968.416.448 1.008.672 1.776.672s1.36-.224 1.776-.672c.416-.448.624-1.104.624-1.968V38.336c0-.352.128-.656.384-.912s.56-.384.912-.384h9.12c.352 0 .656.128.912.384s.384.56.384.912v22.368c0 .352-.128.656-.384.912s-.56.384-.912.384h-8.4c-.352 0-.656-.128-.912-.384a1.246 1.246 0 0 1-.384-.912V59.12c-.768 1.12-1.84 1.968-3.216 2.544-1.376.544-2.96.816-4.752.816zm41.127 0c-3.04 0-5.408-.96-7.104-2.88v1.104c0 .352-.128.656-.384.912s-.56.384-.912.384h-8.16c-.352 0-.656-.128-.912-.384a1.246 1.246 0 0 1-.384-.912V29.216c0-.352.128-.656.384-.912s.56-.384.912-.384h8.88c.352 0 .656.128.912.384s.384.56.384.912v9.6C93.28 37.312 95.408 36.56 98 36.56c2.912 0 5.296.944 7.152 2.832 1.888 1.856 2.896 4.592 3.024 8.208.032.48.048 1.104.048 1.872 0 .8-.016 1.44-.048 1.92-.16 3.808-1.152 6.608-2.976 8.4-1.824 1.792-4.224 2.688-7.2 2.688zm-3.984-8.592c.832 0 1.408-.224 1.728-.672.352-.448.576-1.152.672-2.112.064-.64.096-1.168.096-1.584 0-.416-.032-.944-.096-1.584-.096-.96-.32-1.664-.672-2.112-.32-.448-.896-.672-1.728-.672-.8 0-1.392.208-1.776.624-.352.384-.56.976-.624 1.776-.032.48-.048 1.072-.048 1.776s.016 1.296.048 1.776c.064.928.272 1.632.624 2.112.352.448.944.672 1.776.672zM113.415 34.4c-.352 0-.656-.128-.912-.384a1.246 1.246 0 0 1-.384-.912v-5.808c0-.352.128-.656.384-.912s.56-.384.912-.384h8.112c.352 0 .656.128.912.384s.384.56.384.912v5.808c0 .352-.128.656-.384.912s-.56.384-.912.384h-8.112zm-.24 27.6c-.352 0-.656-.128-.912-.384a1.246 1.246 0 0 1-.384-.912V38.336c0-.352.128-.656.384-.912s.56-.384.912-.384h8.592c.352 0 .656.128.912.384s.384.56.384.912v22.368c0 .352-.128.656-.384.912s-.56.384-.912.384h-8.592zm15.515 0c-.352 0-.656-.128-.912-.384a1.246 1.246 0 0 1-.384-.912V29.216c0-.352.128-.656.384-.912s.56-.384.912-.384h8.4c.352 0 .656.128.912.384s.384.56.384.912v15.552l4.224-6.912c.32-.544.784-.816 1.392-.816h9.696c.32 0 .592.112.816.336.224.224.336.496.336.816 0 .224-.08.464-.24.72l-6.576 9.36 7.776 11.952c.128.192.192.4.192.624 0 .32-.112.592-.336.816a1.11 1.11 0 0 1-.816.336h-10.08c-.64 0-1.136-.272-1.488-.816l-4.896-8.16v7.68c0 .352-.128.656-.384.912s-.56.384-.912.384h-8.4zM25.4 105.48c-3.776 0-6.768-.88-8.976-2.64-2.208-1.76-3.312-4.16-3.312-7.2 0-1.952.56-3.664 1.68-5.136 1.12-1.472 2.72-2.8 4.8-3.984-1.216-1.312-2.096-2.528-2.64-3.648-.512-1.152-.768-2.32-.768-3.504 0-1.536.4-2.944 1.2-4.224.8-1.28 1.984-2.304 3.552-3.072 1.568-.768 3.456-1.152 5.664-1.152 2.048 0 3.824.384 5.328 1.152 1.536.736 2.688 1.744 3.456 3.024a7.494 7.494 0 0 1 1.2 4.128c0 1.856-.56 3.456-1.68 4.8-1.12 1.312-2.784 2.608-4.992 3.888l5.712 5.712c.512-.832.944-1.632 1.296-2.4.384-.8.768-1.84 1.152-3.12.128-.448.464-.672 1.008-.672h4.848c.256 0 .48.096.672.288.192.16.288.368.288.624-.032 1.12-.56 2.64-1.584 4.56-.992 1.92-2.096 3.616-3.312 5.088l5.376 5.424c.224.288.336.528.336.72a.774.774 0 0 1-.288.624.844.844 0 0 1-.624.24h-6.528c-.512 0-.928-.16-1.248-.48l-2.16-2.064c-2.464 2.016-5.616 3.024-9.456 3.024zm.432-21.984c1.28-.64 2.24-1.264 2.88-1.872.672-.608 1.008-1.328 1.008-2.16 0-.864-.304-1.552-.912-2.064-.576-.544-1.312-.816-2.208-.816a3.31 3.31 0 0 0-2.208.816c-.608.544-.912 1.248-.912 2.112 0 .576.176 1.184.528 1.824.384.608.992 1.328 1.824 2.16zM25.4 99.384c1.984 0 3.632-.592 4.944-1.776l-6.384-6.384c-2.112 1.12-3.168 2.48-3.168 4.08 0 1.216.464 2.208 1.392 2.976.928.736 2 1.104 3.216 1.104zM65.56 105h-3.168l-6.24-21.12h2.752l5.088 19.104 4.992-19.104h2.912l4.992 19.168 5.12-19.168H84.6L78.392 105h-3.168L71.48 91.304l-1.088-4.768h-.032l-1.088 4.768L65.56 105zm28.824-16.32c2.41 0 4.299.736 5.664 2.208 1.387 1.472 2.08 3.51 2.08 6.112 0 2.603-.693 4.64-2.08 6.112-1.365 1.472-3.253 2.208-5.664 2.208-2.41 0-4.31-.736-5.696-2.208-1.365-1.472-2.048-3.51-2.048-6.112 0-2.603.683-4.64 2.048-6.112 1.387-1.472 3.286-2.208 5.696-2.208zm0 2.208c-1.621 0-2.89.544-3.808 1.632C89.66 93.608 89.2 95.101 89.2 97c0 1.899.459 3.392 1.376 4.48.918 1.088 2.187 1.632 3.808 1.632 1.622 0 2.89-.544 3.808-1.632.918-1.088 1.376-2.581 1.376-4.48 0-1.899-.458-3.392-1.376-4.48-.917-1.088-2.186-1.632-3.808-1.632zm20.269-2.208c.768 0 1.355.107 1.76.32l-.512 2.496c-.512-.277-1.184-.416-2.016-.416-.683 0-1.355.203-2.016.608-.64.384-1.173.981-1.6 1.792-.405.79-.608 1.75-.608 2.88V105h-2.56V89h2.08l.352 2.624c.896-1.963 2.603-2.944 5.12-2.944zm11.463 8.416l-3.392 3.392V105h-2.56V81.64h2.56v15.648L131.012 89h3.2l-6.24 6.24 6.624 9.76h-3.104l-5.376-7.904zm29.655-13.536c3.776 0 6.496 1.493 8.16 4.48l-2.208 1.792c-.64-1.408-1.408-2.4-2.304-2.976-.874-.597-2.08-.896-3.616-.896-1.621 0-2.901.341-3.84 1.024-.917.661-1.376 1.515-1.376 2.56 0 .683.182 1.248.544 1.696.363.448.96.843 1.792 1.184.854.32 2.027.608 3.52.864 2.795.47 4.768 1.173 5.92 2.112 1.174.939 1.76 2.24 1.76 3.904 0 1.195-.341 2.251-1.024 3.168-.661.896-1.61 1.6-2.848 2.112-1.237.491-2.666.736-4.288.736-2.133 0-3.957-.416-5.472-1.248-1.493-.832-2.634-1.941-3.424-3.328l2.208-1.792c.576 1.259 1.419 2.24 2.528 2.944 1.131.683 2.539 1.024 4.224 1.024 1.664 0 2.987-.299 3.968-.896.982-.619 1.472-1.483 1.472-2.592 0-.939-.426-1.685-1.28-2.24-.853-.555-2.368-1.024-4.544-1.408-2.816-.49-4.81-1.195-5.984-2.112-1.173-.917-1.76-2.197-1.76-3.84 0-1.13.32-2.176.96-3.136.64-.96 1.558-1.717 2.752-2.272 1.195-.576 2.582-.864 4.16-.864zm26.044 19.584a5.25 5.25 0 0 0 1.28-.16l-.16 2.016a5.68 5.68 0 0 1-1.92.32c-.832 0-1.494-.181-1.984-.544-.47-.363-.768-.971-.896-1.824-.491.747-1.216 1.333-2.176 1.76a7.435 7.435 0 0 1-2.976.608c-1.579 0-2.88-.363-3.904-1.088-1.024-.747-1.536-1.813-1.536-3.2 0-1.216.533-2.261 1.6-3.136 1.066-.896 2.613-1.515 4.64-1.856l4.256-.704v-.896c0-1.067-.331-1.92-.992-2.56-.662-.64-1.579-.96-2.752-.96-1.067 0-1.995.256-2.784.768-.768.512-1.366 1.27-1.792 2.272l-1.888-1.376c.426-1.195 1.216-2.144 2.368-2.848 1.173-.704 2.538-1.056 4.096-1.056 1.898 0 3.424.459 4.576 1.376 1.152.917 1.728 2.272 1.728 4.064v7.872c0 .384.096.672.288.864.192.192.501.288.928.288zm-8.704-.064c1.344 0 2.496-.32 3.456-.96.981-.64 1.472-1.472 1.472-2.496v-2.208l-3.584.672c-1.43.256-2.496.63-3.2 1.12-.704.47-1.056 1.077-1.056 1.824 0 .661.256 1.173.768 1.536.512.341 1.226.512 2.144.512zm21.485-14.4c1.813 0 3.306.523 4.48 1.568 1.173 1.045 1.76 2.55 1.76 4.512V105h-2.56v-9.344c0-1.664-.363-2.87-1.088-3.616-.704-.747-1.654-1.12-2.848-1.12-.854 0-1.654.192-2.4.576-.747.363-1.366.97-1.856 1.824-.47.832-.704 1.888-.704 3.168V105h-2.56V89h2.24l.16 2.496c.533-.96 1.269-1.664 2.208-2.112.938-.47 1.994-.704 3.168-.704zm17.476 16.64c-1.536 0-2.922-.299-4.16-.896-1.237-.619-2.144-1.525-2.72-2.72l2.08-1.44a3.898 3.898 0 0 0 1.888 2.112c.896.469 1.952.704 3.168.704 1.259 0 2.219-.224 2.88-.672.662-.448.992-1.013.992-1.696 0-.619-.309-1.11-.928-1.472-.618-.384-1.706-.715-3.264-.992-1.536-.277-2.752-.608-3.648-.992-.896-.405-1.546-.907-1.952-1.504-.405-.619-.608-1.376-.608-2.272 0-.875.256-1.675.768-2.4.512-.725 1.248-1.301 2.208-1.728.96-.448 2.07-.672 3.328-.672 1.707 0 3.072.32 4.096.96 1.046.619 1.792 1.579 2.24 2.88l-2.176 1.28c-.341-1.024-.864-1.76-1.568-2.208-.682-.448-1.546-.672-2.592-.672-1.045 0-1.93.235-2.656.704-.725.47-1.088 1.013-1.088 1.632 0 .704.31 1.248.928 1.632.64.384 1.771.715 3.392.992 2.219.363 3.787.907 4.704 1.632.918.725 1.376 1.75 1.376 3.072a3.95 3.95 0 0 1-.832 2.464c-.533.704-1.312 1.259-2.336 1.664-1.002.405-2.176.608-3.52.608z"
39
- fill="#fff"
40
- />
41
- </SVG>
42
- );
43
- const PlayRoboto = () => (
44
- <SVG width="232" height="132" viewBox="0 0 232 132" xmlns="http://www.w3.org/2000/svg">
45
- <Path fill="#B9B5B8" d="M0 0h232v132H0z" />
46
- <Path
47
- d="M149.438 101c-.75-2.125-1.23-5.27-1.438-9.438-2.625 3.417-5.979 6.063-10.062 7.938-4.042 1.833-8.334 2.75-12.876 2.75-6.5 0-11.77-1.812-15.812-5.438-4-3.624-6-8.208-6-13.75 0-6.583 2.729-11.791 8.188-15.624 5.5-3.834 13.145-5.75 22.937-5.75h13.563V54c0-4.833-1.5-8.625-4.5-11.375-2.959-2.792-7.292-4.188-13-4.188-5.209 0-9.521 1.334-12.938 4-3.417 2.667-5.125 5.876-5.125 9.626l-7.5-.063c0-5.375 2.5-10.02 7.5-13.938 5-3.958 11.146-5.937 18.437-5.937 7.542 0 13.48 1.896 17.813 5.688 4.375 3.75 6.625 9 6.75 15.75v32c0 6.541.687 11.437 2.063 14.687v.75h-8zm-23.5-5.375c5 0 9.458-1.208 13.374-3.625 3.959-2.417 6.834-5.646 8.626-9.688V67.439h-13.376c-7.458.083-13.291 1.458-17.5 4.124-4.208 2.626-6.312 6.25-6.312 10.876 0 3.791 1.396 6.937 4.188 9.437 2.833 2.5 6.5 3.75 11 3.75zM39.328 101.896c-5.461 0-9.6-1.451-12.416-4.352-2.73-2.987-4.096-6.699-4.096-11.136 0-3.84.981-6.997 2.944-9.472 2.048-2.56 4.437-4.523 7.168-5.888 2.73-1.365 6.272-2.773 10.624-4.224 4.608-1.536 7.979-2.944 10.112-4.224 2.133-1.28 3.2-3.072 3.2-5.376V45.832c0-2.73-.683-5.163-2.048-7.296s-3.712-3.2-7.04-3.2c-2.645 0-5.035.725-7.168 2.176 2.901 1.024 5.035 2.56 6.4 4.608 1.45 1.963 2.176 4.181 2.176 6.656 0 3.328-1.195 6.016-3.584 8.064-2.304 1.963-5.12 2.944-8.448 2.944-3.328 0-5.973-1.024-7.936-3.072-1.877-2.133-2.816-4.821-2.816-8.064 0-2.56.64-4.779 1.92-6.656 1.28-1.877 3.285-3.584 6.016-5.12 4.779-2.73 11.605-4.096 20.48-4.096 4.693 0 8.747.47 12.16 1.408 3.413.853 6.315 2.517 8.704 4.992 1.707 1.792 2.816 4.053 3.328 6.784.597 2.645.896 6.357.896 11.136V91.4c0 2.133.128 3.584.384 4.352.341.768.896 1.152 1.664 1.152.597 0 1.237-.17 1.92-.512a15.863 15.863 0 0 0 1.92-1.408l1.28 2.176c-3.67 3.157-8.917 4.736-15.744 4.736-5.12 0-8.704-.853-10.752-2.56-2.048-1.792-3.157-4.181-3.328-7.168-4.01 6.485-9.984 9.728-17.92 9.728zm12.8-10.24c1.792 0 3.37-.725 4.736-2.176V62.472c-.768 1.28-2.176 2.944-4.224 4.992-2.304 2.219-4.053 4.395-5.248 6.528-1.195 2.048-1.792 4.864-1.792 8.448 0 6.144 2.176 9.216 6.528 9.216z"
48
- fill="#270920"
49
- />
50
- </SVG>
51
- );
52
-
53
- export default ( preview, headings, base ) => {
54
- switch ( preview ) {
55
- case 'SPACE_LORA':
56
- return SpaceLora();
57
- case 'SYSTEM_BASKER':
58
- return SystemBasker();
59
- case 'RUBIK_WORK':
60
- return RubikWork();
61
- case 'PLAY_ROBOTO':
62
- return PlayRoboto();
63
- default:
64
- return (
65
- <div className="font-pairings-panel__preview">
66
- <h1 style={ { fontFamily: headings } }>Lorem Ipsum</h1>
67
- <p style={ { fontFamily: base } }>
68
- Etiam tempor orci eu lobortis elementum nibh tellus molestie.
69
- </p>
70
- </div>
71
- );
72
- }
73
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/global-styles/src/font-pairings-panel.js DELETED
@@ -1,50 +0,0 @@
1
- /**
2
- * External dependencies
3
- */
4
- import { ENTER } from '@wordpress/keycodes';
5
- import classnames from 'classnames';
6
- import { __ } from '@wordpress/i18n';
7
-
8
- /**
9
- * Internal dependencies
10
- */
11
- import NoSupport from './no-support';
12
- import loadFontPairingPreview from './font-pairings-panel-previews';
13
-
14
- export default ( { fontPairings, fontBase, fontHeadings, update } ) => {
15
- return (
16
- <>
17
- <h3>{ __( 'Font Pairings' ) }</h3>
18
- { fontPairings && fontHeadings && fontBase ? (
19
- <div role="listbox">
20
- { fontPairings.map( ( { label, headings, base, preview } ) => {
21
- const isSelected = headings === fontHeadings && base === fontBase;
22
- const classes = classnames( 'font-pairings-panel', {
23
- 'is-selected': isSelected,
24
- } );
25
- return (
26
- <div
27
- key={ label }
28
- tabIndex={ 0 }
29
- role="option"
30
- aria-selected={ isSelected }
31
- className={ classes }
32
- onClick={ () => update( { headings, base } ) }
33
- onKeyDown={ event =>
34
- event.keyCode === ENTER ? update( { headings, base } ) : null
35
- }
36
- >
37
- <div className="font-pairings-panel__preview">
38
- { loadFontPairingPreview( preview, headings, base ) }
39
- </div>
40
- <p className="font-pairings-panel__label">{ label }</p>
41
- </div>
42
- );
43
- } ) }
44
- </div>
45
- ) : (
46
- <NoSupport unsupportedFeature={ __( 'font pairings' ) } />
47
- ) }
48
- </>
49
- );
50
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/global-styles/src/font-pairings-panel.scss DELETED
@@ -1,48 +0,0 @@
1
- .font-pairings-panel {
2
- cursor: pointer;
3
- border-radius: 4px;
4
- padding: 4px;
5
- margin-bottom: 0.5em;
6
-
7
- &.is-selected {
8
- box-shadow: 0 0 0 2px #555d66;
9
- }
10
-
11
- &:focus {
12
- box-shadow: 0 0 0 2px #00a0d2;
13
- }
14
-
15
- &:hover {
16
- background-color: #f3f4f5;
17
- color: #191e23;
18
- }
19
- }
20
-
21
- .font-pairings-panel__preview {
22
- border: 1px solid rgba( 25, 30, 35, 0.2 );
23
- border-radius: 4px;
24
- background-color: #fff;
25
- padding: 4px;
26
-
27
- // For when no art directed preview is present.
28
- h1,
29
- p {
30
- margin: 0;
31
- white-space: nowrap;
32
- overflow: hidden;
33
- text-overflow: ellipsis;
34
- padding: 10px 0;
35
- }
36
-
37
- // For the art directed preview.
38
- svg {
39
- display: block;
40
- width: 100%;
41
- height: auto;
42
- }
43
- }
44
-
45
- .font-pairings-panel__label {
46
- text-align: center;
47
- margin-bottom: 0;
48
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/global-styles/src/font-selection-panel.js DELETED
@@ -1,49 +0,0 @@
1
- /**
2
- * External dependencies
3
- */
4
- import { __ } from '@wordpress/i18n';
5
-
6
- /**
7
- * WordPress dependencies.
8
- */
9
- import { SelectControl } from '@wordpress/components';
10
-
11
- /**
12
- * Internal dependencies
13
- */
14
- import NoSupport from './no-support';
15
-
16
- export default ( {
17
- fontBase,
18
- fontBaseDefault,
19
- fontHeadings,
20
- fontHeadingsDefault,
21
- fontBaseOptions,
22
- fontHeadingsOptions,
23
- updateBaseFont,
24
- updateHeadingsFont,
25
- } ) => {
26
- if ( ! fontBaseOptions || ! fontHeadingsOptions ) {
27
- return <NoSupport unsupportedFeature={ __( 'custom font selection' ) } />;
28
- }
29
-
30
- return (
31
- <>
32
- <SelectControl
33
- label={ __( 'Heading Font' ) }
34
- value={ fontHeadings }
35
- options={ fontHeadingsOptions }
36
- onChange={ newValue => updateHeadingsFont( newValue ) }
37
- style={ { fontFamily: fontHeadings !== 'unset' ? fontHeadings : fontHeadingsDefault } }
38
- />
39
- <SelectControl
40
- label={ __( 'Base Font' ) }
41
- value={ fontBase }
42
- options={ fontBaseOptions }
43
- onChange={ newValue => updateBaseFont( newValue ) }
44
- style={ { fontFamily: fontBase !== 'unset' ? fontBase : fontBaseDefault } }
45
- />
46
- <hr />
47
- </>
48
- );
49
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/global-styles/src/global-styles-sidebar.js DELETED
@@ -1,144 +0,0 @@
1
- /**
2
- * External dependencies
3
- */
4
- import { PluginSidebar } from '@wordpress/edit-post';
5
- import { Button, PanelBody } from '@wordpress/components';
6
- import { __, sprintf } from '@wordpress/i18n';
7
- import { PluginSidebarMoreMenuItem } from '@wordpress/edit-post';
8
-
9
- /**
10
- * Internal dependencies
11
- */
12
- import FontPairingsPanel from './font-pairings-panel';
13
- import FontSelectionPanel from './font-selection-panel';
14
- import { GlobalStylesIcon } from './icon';
15
- import { FONT_BASE, FONT_HEADINGS } from './constants';
16
-
17
- const ANY_PROPERTY = 'ANY_PROPERTY';
18
-
19
- const isFor = filterProperty => option =>
20
- option.prop === ANY_PROPERTY || option.prop === filterProperty;
21
-
22
- const toOption = font => {
23
- if ( typeof font === 'object' ) {
24
- const { label, value, prop = ANY_PROPERTY } = font;
25
- return { label, value, prop };
26
- }
27
- return { label: font, value: font, prop: ANY_PROPERTY };
28
- };
29
- const isNotNull = option => option.value !== null && option.label !== null;
30
-
31
- const toOptions = ( options, filterProperty ) =>
32
- ! options
33
- ? []
34
- : options
35
- .map( toOption )
36
- .filter( isNotNull )
37
- .filter( isFor( filterProperty ) );
38
-
39
- const PanelActionButtons = ( {
40
- hasLocalChanges,
41
- resetAction,
42
- publishAction,
43
- className = null,
44
- } ) => (
45
- <div className={ className }>
46
- <Button disabled={ ! hasLocalChanges } isDefault onClick={ resetAction }>
47
- { __( 'Reset' ) }
48
- </Button>
49
- <Button
50
- className={ 'global-styles-sidebar__publish-button' }
51
- disabled={ ! hasLocalChanges }
52
- isPrimary
53
- onClick={ publishAction }
54
- >
55
- { __( 'Publish' ) }
56
- </Button>
57
- </div>
58
- );
59
-
60
- export default ( {
61
- fontHeadings,
62
- fontHeadingsDefault,
63
- fontBase,
64
- fontBaseDefault,
65
- fontPairings,
66
- fontOptions,
67
- siteName,
68
- publishOptions,
69
- updateOptions,
70
- hasLocalChanges,
71
- resetLocalChanges,
72
- } ) => {
73
- const publish = () =>
74
- publishOptions( {
75
- [ FONT_BASE ]: fontBase,
76
- [ FONT_HEADINGS ]: fontHeadings,
77
- } );
78
- return (
79
- <>
80
- <PluginSidebarMoreMenuItem icon={ <GlobalStylesIcon /> } target="global-styles">
81
- { __( 'Global Styles' ) }
82
- </PluginSidebarMoreMenuItem>
83
- <PluginSidebar
84
- icon={ <GlobalStylesIcon /> }
85
- name={ 'global-styles' }
86
- title={ __( 'Global Styles' ) }
87
- className="global-styles-sidebar"
88
- >
89
- <PanelBody>
90
- <p>
91
- { /* translators: %s: Name of site. */
92
- sprintf( __( 'You are customizing %s.' ), siteName ) }
93
- </p>
94
- <p>{ __( 'Any change you make here will apply to the entire website.' ) }</p>
95
- { hasLocalChanges ? (
96
- <div>
97
- <p>
98
- <em>{ __( 'You have unsaved changes.' ) }</em>
99
- </p>
100
- <PanelActionButtons
101
- hasLocalChanges={ hasLocalChanges }
102
- publishAction={ publish }
103
- resetAction={ resetLocalChanges }
104
- />
105
- </div>
106
- ) : null }
107
- </PanelBody>
108
- <PanelBody title={ __( 'Font Selection' ) }>
109
- <FontSelectionPanel
110
- fontBase={ fontBase }
111
- fontBaseDefault={ fontBaseDefault }
112
- fontHeadings={ fontHeadings }
113
- fontHeadingsDefault={ fontHeadingsDefault }
114
- fontBaseOptions={ toOptions( fontOptions, FONT_BASE ) }
115
- fontHeadingsOptions={ toOptions( fontOptions, FONT_HEADINGS ) }
116
- updateBaseFont={ value => updateOptions( { [ FONT_BASE ]: value } ) }
117
- updateHeadingsFont={ value => updateOptions( { [ FONT_HEADINGS ]: value } ) }
118
- />
119
- <FontPairingsPanel
120
- fontHeadings={ fontHeadings }
121
- fontBase={ fontBase }
122
- fontPairings={ fontPairings }
123
- update={ ( { headings, base } ) =>
124
- updateOptions( { [ FONT_HEADINGS ]: headings, [ FONT_BASE ]: base } )
125
- }
126
- />
127
- </PanelBody>
128
- <PanelBody>
129
- { hasLocalChanges ? (
130
- <p>
131
- <em>{ __( 'You have unsaved changes.' ) }</em>
132
- </p>
133
- ) : null }
134
- <PanelActionButtons
135
- hasLocalChanges={ hasLocalChanges }
136
- publishAction={ publish }
137
- resetAction={ resetLocalChanges }
138
- className={ 'global-styles-sidebar__panel-action-buttons' }
139
- />
140
- </PanelBody>
141
- </PluginSidebar>
142
- </>
143
- );
144
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/global-styles/src/global-styles-sidebar.scss DELETED
@@ -1,22 +0,0 @@
1
- .global-styles-sidebar {
2
- // Make the font dropdown a bit more spacy.
3
- .components-select-control__input {
4
- line-height: 1;
5
- font-size: 18px;
6
- height: 36px;
7
- }
8
-
9
- h3 {
10
- margin: 0 0 1em;
11
- }
12
- }
13
-
14
- .global-styles-sidebar__panel-action-buttons {
15
- display: flex;
16
- justify-content: flex-end;
17
- margin-bottom: 96px;
18
- }
19
-
20
- .global-styles-sidebar__publish-button {
21
- margin-left: 1em;
22
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/global-styles/src/icon.js DELETED
@@ -1,12 +0,0 @@
1
- /**
2
- * External dependencies
3
- */
4
- import { Path, SVG } from '@wordpress/components';
5
-
6
- // For now, this icon shows a font style picker. Once we add colors, we'll want colors.
7
-
8
- export const GlobalStylesIcon = () => (
9
- <SVG xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
10
- <Path d="M9.93 13.5h4.14L12 7.98zM20 2H4c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-4.05 16.5l-1.14-3H9.17l-1.12 3H5.96l5.11-13h1.86l5.11 13h-2.09z" />
11
- </SVG>
12
- );
 
 
 
 
 
 
 
 
 
 
 
 
trunk/global-styles/src/no-support.js DELETED
@@ -1,11 +0,0 @@
1
- /**
2
- * External dependencies
3
- */
4
- import { __, sprintf } from '@wordpress/i18n';
5
-
6
- export default ( { unsupportedFeature } ) => (
7
- <p>
8
- { /* translators: %s: feature name (i.e. font pairings, etc) */
9
- sprintf( __( "Your active theme doesn't support %s." ), unsupportedFeature ) }
10
- </p>
11
- );
 
 
 
 
 
 
 
 
 
 
 
trunk/global-styles/src/store.js DELETED
@@ -1,122 +0,0 @@
1
- /**
2
- * External dependencies
3
- */
4
- import apiFetch from '@wordpress/api-fetch';
5
- import { registerStore } from '@wordpress/data';
6
-
7
- let cache = {};
8
- let alreadyFetchedOptions = false;
9
-
10
- const actions = {
11
- *publishOptions( options ) {
12
- yield {
13
- type: 'IO_PUBLISH_OPTIONS',
14
- options,
15
- };
16
- return {
17
- type: 'PUBLISH_OPTIONS',
18
- options,
19
- };
20
- },
21
- updateOptions( options ) {
22
- return {
23
- type: 'UPDATE_OPTIONS',
24
- options,
25
- };
26
- },
27
- fetchOptions() {
28
- return {
29
- type: 'IO_FETCH_OPTIONS',
30
- };
31
- },
32
- resetLocalChanges() {
33
- return {
34
- type: 'RESET_OPTIONS',
35
- options: cache,
36
- };
37
- },
38
- };
39
-
40
- /**
41
- * Store API
42
- *
43
- * Selectors under `wp.data.select( STORE_NAME )`:
44
- *
45
- * - getOption( String optionName )
46
- * - hasLocalChanges()
47
- *
48
- * Actions under `wp.data.dispatch( STORE_NAME )`:
49
- *
50
- * - updateOptions( Object optionsToUpdate )
51
- * - publishOptions( Object optionsToUpdate )
52
- * - resetLocalChanges()
53
- *
54
- * @param {string} storeName Name of the store.
55
- * @param {string} optionsPath REST path used to interact with the options API.
56
- */
57
- export default ( storeName, optionsPath ) => {
58
- registerStore( storeName, {
59
- reducer( state, action ) {
60
- switch ( action.type ) {
61
- case 'UPDATE_OPTIONS':
62
- case 'RESET_OPTIONS':
63
- case 'PUBLISH_OPTIONS':
64
- return {
65
- ...state,
66
- ...action.options,
67
- };
68
- }
69
-
70
- return state;
71
- },
72
-
73
- actions,
74
-
75
- selectors: {
76
- getOption( state, key ) {
77
- return state ? state[ key ] : undefined;
78
- },
79
- hasLocalChanges( state ) {
80
- return !! state && Object.keys( cache ).some( key => cache[ key ] !== state[ key ] );
81
- },
82
- },
83
-
84
- resolvers: {
85
- *getOption( key ) {
86
- // eslint-disable-line no-unused-vars
87
- if ( alreadyFetchedOptions ) {
88
- return; // do nothing
89
- }
90
-
91
- let options;
92
- try {
93
- alreadyFetchedOptions = true;
94
- options = yield actions.fetchOptions();
95
- } catch ( error ) {
96
- options = {};
97
- }
98
- cache = options;
99
- return {
100
- type: 'UPDATE_OPTIONS',
101
- options,
102
- };
103
- },
104
- },
105
-
106
- controls: {
107
- IO_FETCH_OPTIONS() {
108
- return apiFetch( { path: optionsPath } );
109
- },
110
- IO_PUBLISH_OPTIONS( { options } ) {
111
- cache = options; // optimistically update the cache
112
- return apiFetch( {
113
- path: optionsPath,
114
- method: 'POST',
115
- data: {
116
- ...options,
117
- },
118
- } );
119
- },
120
- },
121
- } );
122
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/global-styles/static/blank.css DELETED
@@ -1,6 +0,0 @@
1
- /**
2
- * DO NOT DELETE.
3
- *
4
- * Placeholder file so we can use wp_add_inline_styles
5
- * to dynamically add fonts, custom properties, etc.
6
- */
 
 
 
 
 
 
trunk/global-styles/static/style.css DELETED
@@ -1,28 +0,0 @@
1
- h1,
2
- h2,
3
- h3,
4
- h4,
5
- h5,
6
- h6,
7
- .editor-post-title .editor-post-title__block .editor-post-title__input,
8
- h1.entry-title.entry-title,
9
- .entry-title.entry-title {
10
- font-family: var(--font-headings, var(--font-headings-default));
11
- }
12
-
13
- body,
14
- p,
15
- li {
16
- font-family: var(--font-base, var(--font-base-default));
17
- }
18
-
19
- /*
20
- * Despite best efforts, some fonts bleed into placeholders.
21
- * Unstyle these after the fact.
22
- */
23
- .components-placeholder p,
24
- .components-placeholder li,
25
- .a8c-media-placeholder p,
26
- .a8c-media-placeholder li {
27
- font-family: inherit;
28
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/posts-list-block/blocks/posts-list/block.json DELETED
@@ -1,10 +0,0 @@
1
- {
2
- "name": "a8c/posts-list",
3
- "category": "layout",
4
- "attributes": {
5
- "postsPerPage": {
6
- "type": "number",
7
- "default": 10
8
- }
9
- }
10
- }
 
 
 
 
 
 
 
 
 
 
trunk/posts-list-block/blocks/posts-list/editor.scss DELETED
@@ -1,9 +0,0 @@
1
- div.posts-list__notice {
2
- margin: 0 0 5px;
3
-
4
- .components-notice__content {
5
- display: flex;
6
- align-items: center;
7
- justify-content: space-between;
8
- }
9
- }
 
 
 
 
 
 
 
 
 
trunk/posts-list-block/blocks/posts-list/index.js DELETED
@@ -1,110 +0,0 @@
1
- /* eslint-disable import/no-extraneous-dependencies */
2
- /**
3
- * WordPress dependencies
4
- */
5
- import {
6
- registerBlockType,
7
- switchToBlockType,
8
- getPossibleBlockTransformations,
9
- } from '@wordpress/blocks';
10
- import { __ } from '@wordpress/i18n';
11
- import { Placeholder, RangeControl, PanelBody, Notice } from '@wordpress/components';
12
- import { Fragment } from '@wordpress/element';
13
- import { InspectorControls } from '@wordpress/block-editor';
14
- import { select, dispatch } from '@wordpress/data';
15
- /* eslint-enable import/no-extraneous-dependencies */
16
-
17
- /**
18
- * Internal dependencies
19
- */
20
- import * as metadata from './block.json';
21
- import './editor.scss';
22
- import './style.scss';
23
- import { transforms, isValidHomepagePostsBlockType } from './transforms';
24
-
25
- const icon = (
26
- <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
27
- <path opacity=".87" fill="none" d="M0 0h24v24H0V0z" />
28
- <path d="M3 5v14h17V5H3zm4 2v2H5V7h2zm-2 6v-2h2v2H5zm0 2h2v2H5v-2zm13 2H9v-2h9v2zm0-4H9v-2h9v2zm0-4H9V7h9v2z" />
29
- </svg>
30
- );
31
-
32
- registerBlockType( metadata.name, {
33
- title: __( 'Blog Posts Listing', 'full-site-editing' ),
34
- description: __( 'Displays your latest Blog Posts.', 'full-site-editing' ),
35
- icon: icon,
36
- category: 'layout',
37
- supports: {
38
- html: false,
39
- multiple: false,
40
- reusable: false,
41
- inserter: false,
42
- },
43
- attributes: metadata.attributes,
44
- edit: ( { attributes, setAttributes, clientId, isSelected } ) => {
45
- const block = select( 'core/block-editor' ).getBlock( clientId );
46
-
47
- // Find if any of possible transformations is into the Homepage Posts block.
48
- const possibleTransforms = getPossibleBlockTransformations( [ block ] );
49
- const homepagePostsTransform = possibleTransforms.find(
50
- transform => transform && isValidHomepagePostsBlockType( transform.name )
51
- );
52
- const canBeUpgraded = !! homepagePostsTransform;
53
-
54
- const upgradeBlock = () => {
55
- dispatch( 'core/block-editor' ).replaceBlocks(
56
- block.clientId,
57
- switchToBlockType( block, homepagePostsTransform.name )
58
- );
59
- };
60
-
61
- return (
62
- <Fragment>
63
- { canBeUpgraded && (
64
- <Notice
65
- actions={ [
66
- {
67
- label: __( 'Update Block', 'full-site-editing' ),
68
- onClick: upgradeBlock,
69
- },
70
- ] }
71
- className="posts-list__notice"
72
- isDismissible={ false }
73
- >
74
- { __(
75
- 'An improved version of this block is available. Update for a better, more natural way to manage your blog post listings. There may be small visual changes.',
76
- 'full-site-editing'
77
- ) }
78
- </Notice>
79
- ) }
80
- <Placeholder
81
- icon={ icon }
82
- label={ __( 'Your recent blog posts will be displayed here.', 'full-site-editing' ) }
83
- >
84
- { isSelected ? (
85
- <RangeControl
86
- label={ __( 'Number of posts to show', 'full-site-editing' ) }
87
- value={ attributes.postsPerPage }
88
- onChange={ val => setAttributes( { postsPerPage: val } ) }
89
- min={ 1 }
90
- max={ 50 }
91
- />
92
- ) : null }
93
- </Placeholder>
94
- <InspectorControls>
95
- <PanelBody>
96
- <RangeControl
97
- label={ __( 'Number of posts', 'full-site-editing' ) }
98
- value={ attributes.postsPerPage }
99
- onChange={ val => setAttributes( { postsPerPage: val } ) }
100
- min={ 1 }
101
- max={ 50 }
102
- />
103
- </PanelBody>
104
- </InspectorControls>
105
- </Fragment>
106
- );
107
- },
108
- save: () => null,
109
- transforms,
110
- } );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/posts-list-block/blocks/posts-list/style.scss DELETED
@@ -1,9 +0,0 @@
1
- .a8c-posts-list__listing {
2
- list-style: none;
3
- margin: 0;
4
- padding: 0;
5
- }
6
-
7
- .a8c-posts-list__item {
8
- display: block;
9
- }
 
 
 
 
 
 
 
 
 
trunk/posts-list-block/blocks/posts-list/transforms.js DELETED
@@ -1,34 +0,0 @@
1
- /**
2
- * External dependencies
3
- */
4
-
5
- /* eslint-disable import/no-extraneous-dependencies */
6
- /**
7
- * WordPress dependencies
8
- */
9
- import { createBlock } from '@wordpress/blocks';
10
- /* eslint-enable import/no-extraneous-dependencies */
11
-
12
- const HOMEPAGE_POSTS_BLOCK_TYPES = [ 'a8c/blog-posts', 'newspack-blocks/homepage-articles' ];
13
-
14
- const getTransformFunction = type => ( { postsPerPage } ) => {
15
- // Configure the Newspack block to look as close as possible
16
- // to the output of this one.
17
- return createBlock( type, {
18
- postsToShow: postsPerPage,
19
- showAvatar: false,
20
- displayPostDate: true,
21
- displayPostContent: true,
22
- } );
23
- };
24
-
25
- export const isValidHomepagePostsBlockType = type =>
26
- HOMEPAGE_POSTS_BLOCK_TYPES.indexOf( type ) > -1;
27
-
28
- export const transforms = {
29
- to: HOMEPAGE_POSTS_BLOCK_TYPES.map( type => ( {
30
- type: 'block',
31
- blocks: [ type ],
32
- transform: getTransformFunction( type ),
33
- } ) ),
34
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/posts-list-block/class-posts-list-block.php DELETED
@@ -1,160 +0,0 @@
1
- <?php
2
- /**
3
- * Posts list block file.
4
- *
5
- * @package A8C\FSE
6
- */
7
-
8
- namespace A8C\FSE;
9
-
10
- /**
11
- * Class Post_List_Block
12
- */
13
- class Posts_List_Block {
14
-
15
- /**
16
- * Class instance.
17
- *
18
- * @var \A8C\FSE\Posts_List_Block
19
- */
20
- private static $instance = null;
21
-
22
- /**
23
- * Whether we are in the process of rendering the block.
24
- *
25
- * @var bool
26
- */
27
- private $rendering_block = false;
28
-
29
- /**
30
- * A8C_Post_List constructor.
31
- */
32
- private function __construct() {
33
- add_action( 'init', array( $this, 'register_blocks' ), 100 );
34
- add_action( 'enqueue_block_editor_assets', array( $this, 'enqueue_scripts' ), 100 );
35
- add_action( 'enqueue_block_assets', array( $this, 'enqueue_styles' ), 100 );
36
- }
37
-
38
- /**
39
- * Creates instance.
40
- *
41
- * @return \A8C\FSE\Posts_List_Block
42
- */
43
- public static function get_instance() {
44
- if ( null === self::$instance ) {
45
- self::$instance = new self();
46
- }
47
-
48
- return self::$instance;
49
- }
50
-
51
- /**
52
- * Enqueue block editor scripts.
53
- */
54
- public function enqueue_scripts() {
55
- $asset_file = include plugin_dir_path( __FILE__ ) . 'dist/posts-list-block.asset.php';
56
- $script_dependencies = $asset_file['dependencies'];
57
- wp_enqueue_script(
58
- 'a8c-posts-list-script',
59
- plugins_url( 'dist/posts-list-block.js', __FILE__ ),
60
- is_array( $script_dependencies ) ? $script_dependencies : array(),
61
- filemtime( plugin_dir_path( __FILE__ ) . 'dist/posts-list-block.js' ),
62
- true
63
- );
64
-
65
- wp_set_script_translations( 'a8c-posts-list-script', 'full-site-editing' );
66
- }
67
-
68
- /**
69
- * Enqueue block styles.
70
- */
71
- public function enqueue_styles() {
72
- $style_file = is_rtl()
73
- ? 'posts-list-block.rtl.css'
74
- : 'posts-list-block.css';
75
- wp_enqueue_style(
76
- 'posts-list-block-style',
77
- plugins_url( 'dist/' . $style_file, __FILE__ ),
78
- array(),
79
- filemtime( plugin_dir_path( __FILE__ ) . 'dist/' . $style_file )
80
- );
81
- }
82
-
83
- /**
84
- * Register block.
85
- */
86
- public function register_blocks() {
87
- register_block_type(
88
- 'a8c/posts-list',
89
- array(
90
- 'attributes' => array(
91
- 'postsPerPage' => array(
92
- 'type' => 'number',
93
- 'default' => 10,
94
- ),
95
- ),
96
- 'render_callback' => array( $this, 'render_a8c_post_list_block' ),
97
- )
98
- );
99
- }
100
-
101
- /**
102
- * Renders posts list.
103
- *
104
- * @param array $attributes Block attributes.
105
- * @param string $content Block content.
106
- * @return string
107
- */
108
- public function render_a8c_post_list_block( $attributes, $content ) {
109
-
110
- $posts_list = new \WP_Query(
111
- array(
112
- 'post_type' => 'post',
113
- 'posts_per_page' => $attributes['postsPerPage'],
114
- 'post_status' => 'publish',
115
- 'suppress_filters' => false,
116
- )
117
- );
118
-
119
- add_filter( 'excerpt_more', array( $this, 'custom_excerpt_read_more' ) );
120
-
121
- // Prevent situations when the block attempts rendering another a8c/posts-list block.
122
- if ( $this->rendering_block !== true ) {
123
- $this->rendering_block = true;
124
-
125
- $content = render_template(
126
- 'posts-list',
127
- array(
128
- 'posts_list' => $posts_list,
129
- )
130
- );
131
-
132
- $this->rendering_block = false;
133
- }
134
-
135
- remove_filter( 'excerpt_more', array( $this, 'custom_excerpt_read_more' ) );
136
-
137
- // Reset the custom query.
138
- wp_reset_postdata();
139
-
140
- return $content;
141
- }
142
-
143
- /**
144
- * Excerpt more string.
145
- *
146
- * @return string More string.
147
- */
148
- public function custom_excerpt_read_more() {
149
- return sprintf(
150
- '&hellip; <a href="%1$s" title="%2$s" class="a8c-posts-list-item__read-more">%3$s</a>',
151
- esc_url( get_the_permalink() ),
152
- sprintf(
153
- /* translators: %s: Name of current post */
154
- esc_attr__( 'Continue reading %s', 'full-site-editing' ),
155
- the_title_attribute( array( 'echo' => false ) )
156
- ),
157
- esc_html__( 'Read more', 'full-site-editing' )
158
- );
159
- }
160
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/posts-list-block/dist/posts-list-block.asset.php DELETED
@@ -1 +0,0 @@
1
- <?php return array('dependencies' => array('wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-i18n', 'wp-polyfill'), 'version' => '2d46fa6b50eef5817f491385a0848338');
 
trunk/posts-list-block/dist/posts-list-block.css DELETED
@@ -1 +0,0 @@
1
- div.posts-list__notice{margin:0 0 5px}div.posts-list__notice .components-notice__content{display:flex;align-items:center;justify-content:space-between}.a8c-posts-list__listing{list-style:none;margin:0;padding:0}.a8c-posts-list__item{display:block}
 
trunk/posts-list-block/dist/posts-list-block.js DELETED
@@ -1 +0,0 @@
1
- !function(e,t){for(var n in t)e[n]=t[n]}(window,function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(o,r,function(t){return e[t]}.bind(null,r));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=9)}([function(e,t){!function(){e.exports=this.wp.element}()},function(e,t){!function(){e.exports=this.wp.i18n}()},function(e,t){!function(){e.exports=this.wp.blocks}()},function(e,t){!function(){e.exports=this.wp.components}()},function(e,t){!function(){e.exports=this.wp.data}()},function(e){e.exports=JSON.parse('{"b":"a8c/posts-list","a":{"postsPerPage":{"type":"number","default":10}}}')},function(e,t){!function(){e.exports=this.wp.blockEditor}()},function(e,t,n){},function(e,t,n){},function(e,t,n){"use strict";n.r(t);var o=n(0),r=n(2),i=n(1),l=n(3),s=n(6),c=n(4),a=n(5),u=(n(7),n(8),["a8c/blog-posts","newspack-blocks/homepage-articles"]),f=function(e){return function(t){var n=t.postsPerPage;return Object(r.createBlock)(e,{postsToShow:n,showAvatar:!1,displayPostDate:!0,displayPostContent:!0})}},p={to:u.map((function(e){return{type:"block",blocks:[e],transform:f(e)}}))},b=Object(o.createElement)("svg",{xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24"},Object(o.createElement)("path",{opacity:".87",fill:"none",d:"M0 0h24v24H0V0z"}),Object(o.createElement)("path",{d:"M3 5v14h17V5H3zm4 2v2H5V7h2zm-2 6v-2h2v2H5zm0 2h2v2H5v-2zm13 2H9v-2h9v2zm0-4H9v-2h9v2zm0-4H9V7h9v2z"}));Object(r.registerBlockType)(a.b,{title:Object(i.__)("Blog Posts Listing","full-site-editing"),description:Object(i.__)("Displays your latest Blog Posts.","full-site-editing"),icon:b,category:"layout",supports:{html:!1,multiple:!1,reusable:!1,inserter:!1},attributes:a.a,edit:function(e){var t=e.attributes,n=e.setAttributes,a=e.clientId,f=e.isSelected,p=Object(c.select)("core/block-editor").getBlock(a),d=Object(r.getPossibleBlockTransformations)([p]).find((function(e){return e&&(t=e.name,u.indexOf(t)>-1);var t})),m=!!d;return Object(o.createElement)(o.Fragment,null,m&&Object(o.createElement)(l.Notice,{actions:[{label:Object(i.__)("Update Block","full-site-editing"),onClick:function(){Object(c.dispatch)("core/block-editor").replaceBlocks(p.clientId,Object(r.switchToBlockType)(p,d.name))}}],className:"posts-list__notice",isDismissible:!1},Object(i.__)("An improved version of this block is available. Update for a better, more natural way to manage your blog post listings. There may be small visual changes.","full-site-editing")),Object(o.createElement)(l.Placeholder,{icon:b,label:Object(i.__)("Your recent blog posts will be displayed here.","full-site-editing")},f?Object(o.createElement)(l.RangeControl,{label:Object(i.__)("Number of posts to show","full-site-editing"),value:t.postsPerPage,onChange:function(e){return n({postsPerPage:e})},min:1,max:50}):null),Object(o.createElement)(s.InspectorControls,null,Object(o.createElement)(l.PanelBody,null,Object(o.createElement)(l.RangeControl,{label:Object(i.__)("Number of posts","full-site-editing"),value:t.postsPerPage,onChange:function(e){return n({postsPerPage:e})},min:1,max:50}))))},save:function(){return null},transforms:p})}]));
 
trunk/posts-list-block/dist/posts-list-block.rtl.css DELETED
@@ -1 +0,0 @@
1
- div.posts-list__notice{margin:0 0 5px}div.posts-list__notice .components-notice__content{display:flex;align-items:center;justify-content:space-between}.a8c-posts-list__listing{list-style:none;margin:0;padding:0}.a8c-posts-list__item{display:block}
 
trunk/posts-list-block/index.js DELETED
@@ -1,4 +0,0 @@
1
- /**
2
- * Internal dependencies
3
- */
4
- import './blocks/posts-list';
 
 
 
 
trunk/posts-list-block/templates/no-posts.php DELETED
@@ -1,26 +0,0 @@
1
- <?php
2
- /**
3
- * Template for displaying a message that posts cannot be found.
4
- *
5
- * @package full-site-editing
6
- * @link https://developer.wordpress.org/themes/basics/template-hierarchy/
7
- */
8
-
9
- ?>
10
-
11
- <p><?php esc_html_e( 'There are currently no posts to display.', 'full-site-editing' ); ?></p>
12
- <?php
13
- if ( current_user_can( 'publish_posts' ) ) :
14
- printf(
15
- '<p>' . wp_kses(
16
- /* translators: 1: link to WP admin new post page. */
17
- __( 'Ready to publish your first post? <a href="%1$s">Get started here</a>.', 'full-site-editing' ),
18
- array(
19
- 'a' => array(
20
- 'href' => array(),
21
- ),
22
- )
23
- ) . '</p>',
24
- esc_url( admin_url( 'post-new.php' ) )
25
- );
26
- endif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/posts-list-block/templates/post-item.php DELETED
@@ -1,44 +0,0 @@
1
- <?php
2
- /**
3
- * Post Item.
4
- *
5
- * @package full-site-editing
6
- *
7
- * phpcs:disable WordPress.XSS.EscapeOutput.OutputNotEscaped
8
- */
9
-
10
- ?>
11
-
12
- <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
13
- <?php if ( has_post_thumbnail() ) : ?>
14
- <figure class="a8c-posts-list-item__post-thumbnail">
15
- <a href="<?php the_permalink(); ?>">
16
- <?php the_post_thumbnail( 'post-thumbnail' ); ?>
17
- </a>
18
- </figure>
19
- <?php endif; // has_post_thumbnail. ?>
20
-
21
- <?php if ( is_sticky() ) : ?>
22
- <div class="a8c-posts-list-item__featured">
23
- <span><?php esc_html_e( 'Featured', 'full-site-editing' ); ?></span>
24
- </div>
25
- <?php endif; // is_sticky. ?>
26
-
27
- <?php the_title( sprintf( '<h2 class="a8c-posts-list-item__title"><a href="%s" rel="bookmark">', esc_url( get_permalink() ) ), '</a></h2>' ); ?>
28
-
29
- <div class="a8c-posts-list-item__meta">
30
- <span class="a8c-posts-list-item__datetime"><?php echo esc_html( get_the_time( get_option( 'date_format' ) ) ); ?></span>
31
- <span class="a8c-posts-list-item__author"><?php echo esc_html_x( 'by', 'designating the post author (eg: by John Doe', 'full-site-editing' ); ?>
32
- <?php the_author_posts_link(); ?>
33
- </span>
34
- <?php if ( current_user_can( 'edit_posts' ) ) : ?>
35
- <span class="a8c-posts-list-item__edit-link">
36
- <a href="<?php echo esc_attr( get_edit_post_link() ); ?>"><?php esc_html_e( 'Edit', 'full-site-editing' ); ?></a>
37
- </span>
38
- <?php endif ?>
39
- </div>
40
-
41
- <div class="a8c-posts-list-item__excerpt">
42
- <?php the_excerpt(); ?>
43
- </div>
44
- </article>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/posts-list-block/templates/posts-list.php DELETED
@@ -1,39 +0,0 @@
1
- <?php
2
- /**
3
- * Posts List
4
- *
5
- * @package full-site-editing
6
- */
7
-
8
- /**
9
- * Posts list.
10
- *
11
- * @global \WP_Query $posts_list
12
- */
13
- global $posts_list;
14
-
15
- if ( $posts_list instanceof WP_Query && $posts_list->have_posts() ) :
16
- ?>
17
- <div class="a8c-posts-list">
18
- <ul class="a8c-posts-list__listing">
19
- <?php
20
- while ( $posts_list->have_posts() ) :
21
- $posts_list->the_post();
22
- ?>
23
- <li class="a8c-posts-list__item">
24
- <?php require dirname( __FILE__ ) . '/post-item.php'; ?>
25
- </li>
26
- <?php endwhile; ?>
27
- </ul>
28
-
29
- <a href="<?php echo esc_url( get_post_type_archive_link( 'post' ) ); ?>" class="a8c-posts-list__view-all">
30
- <?php esc_html_e( 'View all posts', 'full-site-editing' ); ?>
31
- </a>
32
- </div>
33
- <?php
34
- else :
35
- // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
36
- echo A8C\FSE\render_template( 'no-posts' );
37
- endif;
38
-
39
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/posts-list-block/utils.php DELETED
@@ -1,46 +0,0 @@
1
- <?php
2
- /**
3
- * Template functions.
4
- *
5
- * @package A8C\FSE
6
- */
7
-
8
- namespace A8C\FSE;
9
-
10
- /**
11
- * OUTPUT BUFFERED LOAD TEMPLATE PART.
12
- *
13
- * Loads a given template using output buffering.
14
- * Optionally including $data to be passed into template.
15
- *
16
- * @param string $template_name Name of the template to be located.
17
- * @param array $data Optional. Associative array of data to be passed into the template. Default empty array.
18
- * @return string
19
- */
20
- function render_template( $template_name, $data = array() ) {
21
-
22
- if ( ! strpos( $template_name, '.php' ) ) {
23
- $template_name = $template_name . '.php';
24
- }
25
-
26
- $template_file = __DIR__ . '/templates/' . $template_name;
27
-
28
- if ( ! file_exists( $template_file ) ) {
29
- return '';
30
- }
31
-
32
- // Optionally provided an assoc array of data to pass to template
33
- // and it will be extracted into variables.
34
- if ( is_array( $data ) ) {
35
- foreach ( $data as $name => $value ) {
36
- $GLOBALS[ $name ] = $value;
37
- }
38
- }
39
-
40
- ob_start();
41
- require_once $template_file;
42
- $content = ob_get_contents();
43
- ob_end_clean();
44
-
45
- return $content;
46
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/readme.txt DELETED
@@ -1,136 +0,0 @@
1
- === Full Site Editing ===
2
- Contributors: alexislloyd, allancole, automattic, codebykat, copons, dmsnell, get_dave, glendaviesnz, gwwar, iamtakashi, Joen, kwight, marekhrabe, mattwiebe, mmtr86, mppfeiffer, nrqsnchz, obenland, okenobi, vindl, noahtallen, owolski, nosolosw
3
- Tags: block, blocks, editor, gutenberg, page
4
- Requires at least: 5.0
5
- Tested up to: 5.3
6
- Stable tag: 0.18
7
- Requires PHP: 5.6.20
8
- License: GPLv2 or later
9
- License URI: https://www.gnu.org/licenses/gpl-2.0.html
10
-
11
- Enhances your page creation workflow within the Block Editor.
12
-
13
-
14
- == Description ==
15
-
16
- This plugin comes with a custom block to display a list of your most recent blog posts, as well as a template selector
17
- to give you a head start on creating new pages for your site.
18
-
19
-
20
- == Installation ==
21
-
22
- 1. Upload the plugin files to the `/wp-content/plugins/full-site-editing` directory, or install the plugin through the WordPress plugins screen directly.
23
- 1. Activate the plugin through the 'Plugins' screen in WordPress.
24
- 1. Create a new page and select a template that best suits your needs.
25
- 1. Place the "Blog Posts Listing" block anywhere you want inside the block editor.
26
-
27
-
28
- == Frequently Asked Questions ==
29
-
30
- = Can I use this plugin in production? =
31
-
32
- We'll be making frequent updates to the plugin as we flesh out its feature set. You're welcome to try it, just be aware that it is only designed to work on the WordPress.com environment and could break after an update.
33
-
34
- = How is the Blog Posts Listing block different from the Latest Posts block in Core? =
35
-
36
- It adds an excerpt! And meta information! It really is much more useful, especially if your looking for a block that gives readers a better idea about your latest posts than just the title.
37
-
38
- = Do you provide support for this plugin? =
39
-
40
- This plugin is experimental, so we don't provide any support for it outside of websites hosted on WordPress.com at this time.
41
-
42
-
43
- == Changelog ==
44
-
45
- = 0.18 =
46
- * Blog Posts Block: Tag Exclusion feature
47
- * Blog Posts Block: Image orientation issues resolved.
48
- * Blog Posts Block: Full width alignment issue resolved.
49
-
50
- = 0.17 =
51
- * Introduces Blog Posts block, a better version of Posts List.
52
-
53
- = 0.16.2 =
54
- * Fix for Global Styles. Logged out users weren't getting the fonts properly.
55
-
56
- = 0.16.1 =
57
- * Improve style of the template part preview.
58
- * Consistent back button styles.
59
-
60
- = 0.16 =
61
- * Delegate FSE support detection to themes by leveraging the theme tags.
62
- * Enable Global Styles for all template-first themes.
63
- * Fix back button navigation issues.
64
- * Keep the sidebar layout selector open by default.
65
- * Fix editor styles with new Gutenberg version.
66
- * Click anywhere on header/footer block to Navigate to editor.
67
-
68
- = 0.15.1 =
69
- * Always open the layout selector if the `?new-homepage` query argument exists.
70
-
71
- = 0.15 =
72
- * Add ability to change page layout for existing pages.
73
- * Expose Homepage layouts from other themes in page layout picker.
74
-
75
- = 0.14 =
76
- * Stop using theme classes for template parts to improve support for FSE blocks' style attributes.
77
-
78
- = 0.13 =
79
- * Incorporate Global Styles plugin functionality.
80
- * Side-load images on template insertion.
81
- * Remove widgets menu from wp-admin.
82
-
83
- = 0.12 =
84
- * Change menu order of default pages that FSE creates to 1.
85
-
86
- = 0.11 =
87
- * Add color, background color, font size, and text alignment support to the Site Title, Site Description, and Navigation Menu blocks.
88
-
89
- = 0.10 =
90
- * Update page template selector with template preview.
91
-
92
- = 0.9 =
93
- * Rename wp_template CPT to wp_template_part.
94
-
95
- = 0.7 =
96
- * Change theme support to Maywood instead of Modern Business.
97
- * Improve style support and UX issues.
98
- * Remove featured image support for pages.
99
- * No longer load FSE editor if theme is unsupported.
100
- * Improve autosave support.
101
- * Add embed/shortcode support to header and footer.
102
- * Several other high priority fixes for the FSE editor.
103
-
104
- = 0.6.1 =
105
- * Updates priority of filter so classnames are added properly to the template blocks.
106
-
107
- = 0.6 =
108
- * Fix issues with Edit template and Back to Page functionality.
109
-
110
- = 0.5 =
111
- * Fetch templates data from the API.
112
- * Improve UX flows and fix styling issues.
113
-
114
- = 0.4 =
115
- * Move template data initialization out of the plugin and delegate it to themes.
116
-
117
- = 0.3 =
118
- * Update modal UI.
119
-
120
- = 0.2.2 =
121
- * Posts List Block - fixes Edit link to only display for users with appropriate permissions.
122
-
123
- = 0.2.1 =
124
- * Starter Page Templates - bug fix with sub-locales.
125
- * Starter Page Templates - fix momentum scrolling on Modal on iOS.
126
- * Starter Page Templates - improve comprehension of Templates listing by forcing 2col layout on small viewports.
127
- * Starter Page Templates - introduced version constant for cache busting purposes.
128
-
129
- = 0.2 =
130
- * Bug fixes and performance improvements.
131
-
132
- = 0.1.1 =
133
- * Latest round of updates
134
-
135
- = 0.1 =
136
- * Initial Release
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/starter-page-templates/class-starter-page-templates.php DELETED
@@ -1,262 +0,0 @@
1
- <?php
2
- /**
3
- * Starter page templates file.
4
- *
5
- * @package A8C\FSE
6
- */
7
-
8
- namespace A8C\FSE;
9
-
10
- /**
11
- * Class Starter_Page_Templates
12
- */
13
- class Starter_Page_Templates {
14
-
15
- /**
16
- * Class instance.
17
- *
18
- * @var Starter_Page_Templates
19
- */
20
- private static $instance = null;
21
-
22
- /**
23
- * Cache key for templates array.
24
- *
25
- * @var string
26
- */
27
- public $templates_cache_key;
28
-
29
- /**
30
- * Starter_Page_Templates constructor.
31
- */
32
- private function __construct() {
33
- $this->templates_cache_key = implode(
34
- '_',
35
- [
36
- 'starter_page_templates',
37
- PLUGIN_VERSION,
38
- get_option( 'site_vertical', 'default' ),
39
- get_locale(),
40
- ]
41
- );
42
-
43
- add_action( 'init', [ $this, 'register_scripts' ] );
44
- add_action( 'init', [ $this, 'register_meta_field' ] );
45
- add_action( 'rest_api_init', [ $this, 'register_rest_api' ] );
46
- add_action( 'enqueue_block_editor_assets', [ $this, 'enqueue_assets' ] );
47
- add_action( 'delete_attachment', [ $this, 'clear_sideloaded_image_cache' ] );
48
- add_action( 'switch_theme', [ $this, 'clear_templates_cache' ] );
49
- }
50
-
51
- /**
52
- * Creates instance.
53
- *
54
- * @return \A8C\FSE\Starter_Page_Templates
55
- */
56
- public static function get_instance() {
57
- if ( null === self::$instance ) {
58
- self::$instance = new self();
59
- }
60
-
61
- return self::$instance;
62
- }
63
-
64
- /**
65
- * Register block editor scripts.
66
- */
67
- public function register_scripts() {
68
- wp_register_script(
69
- 'starter-page-templates',
70
- plugins_url( 'dist/starter-page-templates.js', __FILE__ ),
71
- [ 'wp-plugins', 'wp-edit-post', 'wp-element' ],
72
- filemtime( plugin_dir_path( __FILE__ ) . 'dist/starter-page-templates.js' ),
73
- true
74
- );
75
- }
76
-
77
- /**
78
- * Register meta field for storing the template identifier.
79
- */
80
- public function register_meta_field() {
81
- $args = [
82
- 'type' => 'string',
83
- 'description' => 'Selected template',
84
- 'single' => true,
85
- 'show_in_rest' => true,
86
- 'object_subtype' => 'page',
87
- 'auth_callback' => function() {
88
- return current_user_can( 'edit_posts' );
89
- },
90
- ];
91
- register_meta( 'post', '_starter_page_template', $args );
92
- }
93
-
94
- /**
95
- * Register rest api endpoint for side-loading images.
96
- */
97
- public function register_rest_api() {
98
- require_once __DIR__ . '/class-wp-rest-sideload-image-controller.php';
99
-
100
- ( new WP_REST_Sideload_Image_Controller() )->register_routes();
101
- }
102
-
103
- /**
104
- * Pass error message to frontend JavaScript console.
105
- *
106
- * @param string $message Error message.
107
- */
108
- public function pass_error_to_frontend( $message ) {
109
- wp_register_script(
110
- 'starter-page-templates-error',
111
- null,
112
- [],
113
- '1.O',
114
- true
115
- );
116
- wp_add_inline_script(
117
- 'starter-page-templates-error',
118
- sprintf(
119
- 'console.warn(%s);',
120
- wp_json_encode( $message )
121
- )
122
- );
123
- wp_enqueue_script( 'starter-page-templates-error' );
124
- }
125
-
126
- /**
127
- * Enqueue block editor assets.
128
- */
129
- public function enqueue_assets() {
130
- $screen = get_current_screen();
131
-
132
- // Return early if we don't meet conditions to show templates.
133
- if ( 'page' !== $screen->id ) {
134
- return;
135
- }
136
-
137
- // Load templates for this site.
138
- $vertical_data = $this->fetch_vertical_data();
139
- if ( empty( $vertical_data ) ) {
140
- $this->pass_error_to_frontend( __( 'No data received from the vertical API. Skipped showing modal window with template selection.', 'full-site-editing' ) );
141
- return;
142
- }
143
- $vertical = $vertical_data['vertical'];
144
- $segment = $vertical_data['segment'];
145
- $vertical_templates = $vertical_data['templates'];
146
-
147
- // Bail early if we have no templates to offer.
148
- if ( empty( $vertical_templates ) || empty( $vertical ) || empty( $segment ) ) {
149
- $this->pass_error_to_frontend( __( 'No templates available. Skipped showing modal window with template selection.', 'full-site-editing' ) );
150
- return;
151
- }
152
-
153
- wp_enqueue_script( 'starter-page-templates' );
154
- wp_set_script_translations( 'starter-page-templates', 'full-site-editing' );
155
-
156
- $default_info = [
157
- 'title' => get_bloginfo( 'name' ),
158
- 'vertical' => $vertical['name'],
159
- ];
160
- $default_templates = [
161
- [
162
- 'title' => 'Blank',
163
- 'slug' => 'blank',
164
- ],
165
- ];
166
- $site_info = get_option( 'site_contact_info', [] );
167
- /**
168
- * Filters the config before it's passed to the frontend.
169
- *
170
- * @param array $config The config.
171
- */
172
- $config = apply_filters(
173
- 'fse_starter_page_templates_config',
174
- [
175
- 'siteInformation' => array_merge( $default_info, $site_info ),
176
- 'templates' => array_merge( $default_templates, $vertical_templates ),
177
- 'vertical' => $vertical,
178
- 'segment' => $segment,
179
- // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
180
- 'screenAction' => isset( $_GET['new-homepage'] ) ? 'add' : $screen->action,
181
- 'theme' => normalize_theme_slug( get_stylesheet() ),
182
- // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
183
- 'isFrontPage' => isset( $_GET['post'] ) && get_option( 'page_on_front' ) === $_GET['post'],
184
- ]
185
- );
186
- wp_localize_script( 'starter-page-templates', 'starterPageTemplatesConfig', $config );
187
-
188
- // Enqueue styles.
189
- $style_file = is_rtl()
190
- ? 'starter-page-templates.rtl.css'
191
- : 'starter-page-templates.css';
192
-
193
- wp_enqueue_style(
194
- 'starter-page-templates',
195
- plugins_url( 'dist/' . $style_file, __FILE__ ),
196
- [],
197
- filemtime( plugin_dir_path( __FILE__ ) . 'dist/' . $style_file )
198
- );
199
- }
200
-
201
- /**
202
- * Fetch vertical data from the API or return cached version if available.
203
- *
204
- * @return array Containing vertical name and template list or nothing if an error occurred.
205
- */
206
- public function fetch_vertical_data() {
207
- $vertical_templates = get_transient( $this->templates_cache_key );
208
-
209
- // Load fresh data if we don't have any or vertical_id doesn't match.
210
- if ( false === $vertical_templates || ( defined( 'WP_DEBUG' ) && WP_DEBUG ) ) {
211
- $vertical_id = get_option( 'site_vertical', 'default' );
212
- $request_url = add_query_arg(
213
- [ '_locale' => $this->get_iso_639_locale() ],
214
- 'https://public-api.wordpress.com/wpcom/v2/verticals/' . $vertical_id . '/templates'
215
- );
216
- $response = wp_remote_get( esc_url_raw( $request_url ) );
217
- if ( 200 !== wp_remote_retrieve_response_code( $response ) ) {
218
- return [];
219
- }
220
- $vertical_templates = json_decode( wp_remote_retrieve_body( $response ), true );
221
- set_transient( $this->templates_cache_key, $vertical_templates, DAY_IN_SECONDS );
222
- }
223
-
224
- return $vertical_templates;
225
- }
226
-
227
- /**
228
- * Deletes cached attachment data when attachment gets deleted.
229
- *
230
- * @param int $id Attachment ID of the attachment to be deleted.
231
- */
232
- public function clear_sideloaded_image_cache( $id ) {
233
- $url = get_post_meta( $id, '_sideloaded_url', true );
234
- if ( ! empty( $url ) ) {
235
- delete_transient( 'fse_sideloaded_image_' . hash( 'crc32b', $url ) );
236
- }
237
- }
238
-
239
- /**
240
- * Deletes cached templates data when theme switches.
241
- */
242
- public function clear_templates_cache() {
243
- delete_transient( $this->templates_cache_key );
244
- }
245
-
246
- /**
247
- * Returns ISO 639 conforming locale string.
248
- *
249
- * @return string ISO 639 locale string
250
- */
251
- private function get_iso_639_locale() {
252
- $language = strtolower( get_locale() );
253
-
254
- if ( in_array( $language, [ 'zh_tw', 'zh-tw', 'zh_cn', 'zh-cn' ], true ) ) {
255
- $language = str_replace( '_', '-', $language );
256
- } else {
257
- $language = preg_replace( '/([-_].*)$/i', '', $language );
258
- }
259
-
260
- return $language;
261
- }
262
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/starter-page-templates/class-wp-rest-sideload-image-controller.php DELETED
@@ -1,294 +0,0 @@
1
- <?php
2
- /**
3
- * WP_REST_Sideload_Image_Controller file.
4
- *
5
- * @package A8C\FSE
6
- */
7
-
8
- namespace A8C\FSE;
9
-
10
- /**
11
- * Class WP_REST_Sideload_Image_Controller.
12
- */
13
- class WP_REST_Sideload_Image_Controller extends \WP_REST_Attachments_Controller {
14
-
15
- /**
16
- * WP_REST_Sideload_Image_Controller constructor.
17
- */
18
- public function __construct() {
19
- parent::__construct( 'attachment' );
20
-
21
- $this->namespace = 'fse/v1';
22
- $this->rest_base = 'sideload/image';
23
- }
24
-
25
- /**
26
- * Register available routes.
27
- */
28
- public function register_routes() {
29
- register_rest_route(
30
- $this->namespace,
31
- '/' . $this->rest_base,
32
- [
33
- [
34
- 'methods' => \WP_REST_Server::CREATABLE,
35
- 'callback' => [ $this, 'create_item' ],
36
- 'permission_callback' => [ $this, 'create_item_permissions_check' ],
37
- 'show_in_index' => false,
38
- 'args' => $this->get_collection_params(),
39
- ],
40
- 'schema' => [ $this, 'get_item_schema' ],
41
- ]
42
- );
43
-
44
- register_rest_route(
45
- $this->namespace,
46
- '/' . $this->rest_base . '/batch',
47
- [
48
- [
49
- 'methods' => \WP_REST_Server::CREATABLE,
50
- 'callback' => [ $this, 'create_items' ],
51
- 'show_in_index' => false,
52
- 'args' => [
53
- 'resources' => [
54
- 'description' => 'URL to the image to be side-loaded.',
55
- 'type' => 'array',
56
- 'required' => true,
57
- 'items' => [
58
- 'type' => 'object',
59
- 'properties' => $this->get_collection_params(),
60
- ],
61
- ],
62
- ],
63
- ],
64
- ]
65
- );
66
- }
67
-
68
- /**
69
- * Creates a single attachment.
70
- *
71
- * @param \WP_REST_Request $request Full details about the request.
72
- * @return \WP_Error|\WP_REST_Response Response object on success, WP_Error object on failure.
73
- */
74
- public function create_item( $request ) {
75
- if ( ! empty( $request['post_id'] ) && in_array( get_post_type( $request['post_id'] ), [ 'revision', 'attachment' ], true ) ) {
76
- return new \WP_Error( 'rest_invalid_param', __( 'Invalid parent type.' ), [ 'status' => 400 ] );
77
- }
78
-
79
- $inserted = false;
80
- $attachment = $this->get_attachment( $request->get_param( 'url' ) );
81
- if ( ! $attachment ) {
82
- // Include image functions to get access to wp_read_image_metadata().
83
- require_once ABSPATH . 'wp-admin/includes/file.php';
84
- require_once ABSPATH . 'wp-admin/includes/image.php';
85
- require_once ABSPATH . 'wp-admin/includes/media.php';
86
-
87
- // The post ID on success, WP_Error on failure.
88
- $id = media_sideload_image(
89
- $request->get_param( 'url' ),
90
- $request->get_param( 'post_id' ),
91
- null,
92
- 'id'
93
- );
94
-
95
- if ( is_wp_error( $id ) ) {
96
- if ( 'db_update_error' === $id->get_error_code() ) {
97
- $id->add_data( [ 'status' => 500 ] );
98
- } else {
99
- $id->add_data( [ 'status' => 400 ] );
100
- }
101
-
102
- return rest_ensure_response( $id ); // Return error.
103
- }
104
-
105
- $attachment = get_post( $id );
106
-
107
- /**
108
- * Fires after a single attachment is created or updated via the REST API.
109
- *
110
- * @param WP_Post $attachment Inserted or updated attachment object.
111
- * @param WP_REST_Request $request The request sent to the API.
112
- * @param bool $creating True when creating an attachment, false when updating.
113
- */
114
- do_action( 'rest_insert_attachment', $attachment, $request, true );
115
-
116
- if ( isset( $request['alt_text'] ) ) {
117
- update_post_meta( $id, '_wp_attachment_image_alt', sanitize_text_field( $request['alt_text'] ) );
118
- }
119
-
120
- update_post_meta( $id, '_sideloaded_url', $request->get_param( 'url' ) );
121
-
122
- $fields_update = $this->update_additional_fields_for_object( $attachment, $request );
123
-
124
- if ( is_wp_error( $fields_update ) ) {
125
- return $fields_update;
126
- }
127
-
128
- $inserted = true;
129
- $request->set_param( 'context', 'edit' );
130
-
131
- /**
132
- * Fires after a single attachment is completely created or updated via the REST API.
133
- *
134
- * @param WP_Post $attachment Inserted or updated attachment object.
135
- * @param WP_REST_Request $request Request object.
136
- * @param bool $creating True when creating an attachment, false when updating.
137
- */
138
- do_action( 'rest_after_insert_attachment', $attachment, $request, true );
139
- }
140
-
141
- $response = $this->prepare_item_for_response( $attachment, $request );
142
- $response = rest_ensure_response( $response );
143
- $response->header( 'Location', rest_url( sprintf( '%s/%s/%d', 'wp/v2', 'media', $attachment->ID ) ) );
144
-
145
- if ( $inserted ) {
146
- $response->set_status( 201 );
147
- }
148
-
149
- return $response;
150
- }
151
-
152
- /**
153
- * Creates a batch of attachments.
154
- *
155
- * @param \WP_REST_Request $request Full details about the request.
156
- * @return \WP_Error|\WP_REST_Response Response object on success, WP_Error object on failure.
157
- */
158
- public function create_items( $request ) {
159
- $data = [];
160
-
161
- // Foreach request specified in the requests param, run the endpoint.
162
- foreach ( $request['resources'] as $resource ) {
163
- $request = new \WP_REST_Request( 'POST', $this->get_item_route() );
164
-
165
- // Add specified request parameters into the request.
166
- foreach ( $resource as $param_name => $param_value ) {
167
- $request->set_param( $param_name, $param_value );
168
- }
169
-
170
- $response = rest_do_request( $request );
171
- $data[] = $this->prepare_for_collection( $response );
172
- }
173
-
174
- return rest_ensure_response( $data );
175
- }
176
-
177
- /**
178
- * Prepare a response for inserting into a collection of responses.
179
- *
180
- * @param \WP_REST_Response $response Response object.
181
- * @return array|\WP_REST_Response Response data, ready for insertion into collection data.
182
- */
183
- public function prepare_for_collection( $response ) {
184
- if ( ! ( $response instanceof \WP_REST_Response ) ) {
185
- return $response;
186
- }
187
-
188
- $data = (array) $response->get_data();
189
- $server = rest_get_server();
190
-
191
- if ( method_exists( $server, 'get_compact_response_links' ) ) {
192
- $links = call_user_func( [ $server, 'get_compact_response_links' ], $response );
193
- } else {
194
- $links = call_user_func( [ $server, 'get_response_links' ], $response );
195
- }
196
-
197
- if ( ! empty( $links ) ) {
198
- $data['_links'] = $links;
199
- }
200
-
201
- return $data;
202
- }
203
-
204
- /**
205
- * Prepares a single attachment output for response.
206
- *
207
- * @param \WP_Post $post Attachment object.
208
- * @param \WP_REST_Request $request Request object.
209
- * @return \WP_REST_Response Response object.
210
- */
211
- public function prepare_item_for_response( $post, $request ) {
212
- $response = parent::prepare_item_for_response( $post, $request );
213
- $base = 'wp/v2/media';
214
-
215
- foreach ( [ 'self', 'collection', 'about' ] as $link ) {
216
- $response->remove_link( $link );
217
-
218
- }
219
-
220
- $response->add_link( 'self', rest_url( trailingslashit( $base ) . $post->ID ) );
221
- $response->add_link( 'collection', rest_url( $base ) );
222
- $response->add_link( 'about', rest_url( 'wp/v2/types/' . $post->post_type ) );
223
-
224
- return $response;
225
- }
226
-
227
- /**
228
- * Gets the attachment if an image has been sideloaded previously.
229
- *
230
- * @param string $url URL of the image to sideload.
231
- * @return object|bool Attachment object on success, false on failure.
232
- */
233
- public function get_attachment( $url ) {
234
- $cache_key = 'fse_sideloaded_image_' . hash( 'crc32b', $url );
235
- $attachment = get_transient( $cache_key );
236
-
237
- if ( false === $attachment ) {
238
- $attachments = new \WP_Query(
239
- [
240
- 'no_found_rows' => true,
241
- 'posts_per_page' => 1,
242
- 'post_status' => 'inherit',
243
- 'post_type' => 'attachment',
244
- // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
245
- 'meta_query' => [
246
- [
247
- 'key' => '_sideloaded_url',
248
- 'value' => $url,
249
- ],
250
- ],
251
- ]
252
- );
253
-
254
- if ( $attachments->have_posts() ) {
255
- set_transient( $cache_key, $attachments->post );
256
- }
257
- }
258
-
259
- return $attachment;
260
- }
261
-
262
- /**
263
- * Returns the endpoints request parameters.
264
- *
265
- * @return array Request parameters.
266
- */
267
- public function get_collection_params() {
268
- return [
269
- 'url' => [
270
- 'description' => 'URL to the image to be side-loaded.',
271
- 'type' => 'string',
272
- 'required' => true,
273
- 'format' => 'uri',
274
- 'sanitize_callback' => function( $url ) {
275
- return esc_url_raw( strtok( $url, '?' ) );
276
- },
277
- ],
278
- 'post_id' => [
279
- 'description' => 'ID of the post to associate the image with',
280
- 'type' => 'integer',
281
- 'default' => 0,
282
- ],
283
- ];
284
- }
285
-
286
- /**
287
- * Returns the route to sideload a single image.
288
- *
289
- * @return string
290
- */
291
- public function get_item_route() {
292
- return "/{$this->namespace}/{$this->rest_base}";
293
- }
294
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/starter-page-templates/dist/starter-page-templates.asset.php DELETED
@@ -1 +0,0 @@
1
- <?php return array('dependencies' => array('lodash', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-edit-post', 'wp-element', 'wp-i18n', 'wp-nux', 'wp-plugins', 'wp-polyfill', 'wp-url'), 'version' => 'e501904b85a0fcfb52483517057457d1');
 
trunk/starter-page-templates/dist/starter-page-templates.css DELETED
@@ -1 +0,0 @@
1
- .page-template-modal-screen-overlay{animation:none;background-color:transparent;z-index:99}@media screen and (min-width:783px){body:not(.is-fullscreen-mode) .page-template-modal-screen-overlay{left:36px}}@media screen and (min-width:961px){body:not(.is-fullscreen-mode) .page-template-modal-screen-overlay{left:160px}}@media screen and (min-width:783px){body:not(.is-fullscreen-mode).folded .page-template-modal-screen-overlay{left:36px}body:not(.is-fullscreen-mode):not(.folded):not(.auto-fold) .page-template-modal-screen-overlay{left:160px}}body.admin-bar:not(.is-fullscreen-mode) .page-template-modal-screen-overlay{top:46px}@media screen and (min-width:783px){body.admin-bar:not(.is-fullscreen-mode) .page-template-modal-screen-overlay{top:32px}}.page-template-modal{width:100%;height:100vh;animation:none;box-shadow:none;border:none;top:0;left:0;right:0;bottom:0;transform:none;max-width:none;max-height:none;background-color:#eee}.page-template-modal .components-modal__header-heading-container{border:0;clip:rect(1px,1px,1px,1px);-webkit-clip-path:inset(50%);clip-path:inset(50%);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;word-wrap:normal!important}.page-template-modal__close-button{display:block;position:absolute;z-index:20;top:9px;width:36px;height:36px;left:10px}.page-template-modal .components-modal__header:after{display:block;position:absolute;content:" ";border-right:1px solid #e2e4e7;height:100%;left:56px}.page-template-modal .components-modal__content{overflow-y:scroll;-webkit-overflow-scrolling:touch}.page-template-modal__inner{position:relative;margin:0 auto;padding:0 20px 40px}.page-template-modal__list{margin-bottom:20px}.page-template-modal__list .components-base-control__label{border:0;clip:rect(1px,1px,1px,1px);-webkit-clip-path:inset(50%);clip-path:inset(50%);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;word-wrap:normal!important}.template-selector-control__options{display:grid;grid-template-columns:1fr;grid-gap:1.75em}@media screen and (min-width:660px){.template-selector-control__options{margin-top:0;grid-template-columns:repeat(auto-fit,minmax(110px,1fr))}}.template-selector-item__label{display:block;width:100%;font-size:14px;text-align:center;border:2px solid #e2e4e7;border-radius:6px;cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;padding:0;overflow:hidden;background-color:#fff;position:relative;transform:translateZ(0)}.template-selector-item__label .template-selector-item__template-title{width:100%;position:absolute;bottom:0;left:0;height:40px;line-height:40px;background-color:#fff}.template-selector-item__label:focus{box-shadow:0 0 0 1px #fff,0 0 0 3px #00a0d2;outline:2px solid transparent}.template-selector-item__label:hover{border:2px solid #c9c9ca}.template-selector-item__label.is-selected{border:2px solid #555d66;outline:2px solid transparent;outline-offset:-2px}.template-selector-item__label.is-selected:focus{box-shadow:0 0 0 1px #fff,0 0 0 3px #00a0d2;border:2px solid #555d66;outline:4px solid transparent;outline-offset:-4px}.template-selector-item__preview-wrap{width:100%;display:block;margin:0 auto;background:#fff;border-radius:0;overflow:hidden;height:0;padding-top:120%;box-sizing:content-box;position:relative;pointer-events:none;opacity:1;transform:translateZ(0)}@media screen and (min-width:660px){.template-selector-item__preview-wrap{padding-top:100%}}.template-selector-item__preview-wrap.is-rendering{opacity:.5}.template-selector-item__preview-wrap .block-editor-block-list__block,.template-selector-item__preview-wrap .block-editor-block-list__layout{padding:inherit}.template-selector-item__media{width:100%;display:block;position:absolute;top:0;left:0}@media screen and (max-width:659px){.template-selector-control__template:first-child .template-selector-item__preview-wrap{padding-top:0;height:70px}.template-selector-control__template:first-child .template-selector-item__template-title{height:70px;line-height:70px}}@media screen and (min-width:660px){.page-template-modal__form{max-width:20%}}@media screen and (min-width:783px){.page-template-modal__form{max-width:30%}}.page-template-modal__form-title{font-weight:700;margin-bottom:1em;text-align:center}@media screen and (min-width:660px){.page-template-modal__form-title{text-align:left}}.page-template-modal__buttons{position:absolute;right:0;top:0;z-index:10;height:56px;display:flex;align-items:center;padding-right:24px}@media screen and (min-width:660px){.page-template-modal__buttons{display:flex}}.page-template-modal__buttons.is-visually-hidden{border:0;clip:rect(1px,1px,1px,1px);-webkit-clip-path:inset(50%);clip-path:inset(50%);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;word-wrap:normal!important}.page-template-modal__buttons .components-button{height:33px;line-height:32px}.template-selector-preview{display:none;position:fixed;top:157px;bottom:24px;left:calc(20% + 48px);right:24px;background:#fff;border-radius:2px;overflow-x:hidden;overflow-y:auto;box-shadow:0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.12),0 1px 5px 0 rgba(0,0,0,.2)}@media screen and (min-width:660px){.template-selector-preview{display:block}.template-selector-preview.is-blank-preview{align-items:center;display:flex;justify-content:center}}@media screen and (min-width:783px){.template-selector-preview{top:143px;left:calc(30% + 72px)}body:not(.auto-fold):not(.folded) .template-selector-preview{left:calc(30% + 172px)}}@media screen and (min-width:961px){.template-selector-preview{left:calc(30% + 172px)}body.folded .template-selector-preview{left:calc(30% + 72px)}}body.is-fullscreen-mode .template-selector-preview{top:111px}@media screen and (min-width:783px){body.is-fullscreen-mode .template-selector-preview{left:calc(30% + 48px)!important}}.template-selector-preview .edit-post-visual-editor{margin:0;padding:0}.template-selector-preview .editor-styles-wrapper .template-selector-preview__offset-correction{position:relative;top:120px}.template-selector-preview .editor-styles-wrapper .editor-post-title{transform-origin:top center;width:100%;display:block;position:absolute;top:0}.template-selector-preview .editor-styles-wrapper .editor-post-title,.template-selector-preview .editor-styles-wrapper .editor-post-title__block,.template-selector-preview .editor-styles-wrapper .editor-post-title__input{padding-top:0;padding-bottom:0;margin-top:0;margin-bottom:0}.template-selector-preview .editor-styles-wrapper .editor-post-title .editor-post-title__input,.template-selector-preview .editor-styles-wrapper .editor-post-title__block .editor-post-title__input,.template-selector-preview .editor-styles-wrapper .editor-post-title__input .editor-post-title__input{margin:0;padding:0;height:120px;line-height:120px;overflow:hidden;resize:none}.template-selector-preview__placeholder{color:var(--color-text-subtle);font-size:15px;font-weight:400}.block-editor-block-preview__container .editor-styles-wrapper .wp-block{width:100%}.block-editor-block-preview__container .editor-styles-wrapper .wp-block[data-type="core/cover"][data-align=full]{margin:0}.block-editor-block-preview__container .editor-styles-wrapper .wp-block[data-type="core/cover"][data-align=full] .wp-block-cover{padding:0}.block-editor-block-preview__container .editor-styles-wrapper .wp-block-columns>.editor-inner-blocks>.editor-block-list__layout>[data-type="core/column"]>.editor-block-list__block-edit>div>.block-core-columns>.editor-inner-blocks{margin-top:0;margin-bottom:0}.block-editor-block-preview__container .editor-styles-wrapper .block-editor-block-list__block[data-align=full]{margin:0}@media screen and (min-width:600px){.block-editor-block-preview__container .editor-styles-wrapper .block-editor-block-list__block .block-editor-block-list__block-edit{margin:0}}.block-editor-block-preview__container .editor-styles-wrapper .block-editor-block-list__block,.block-editor-block-preview__container .editor-styles-wrapper .block-editor-block-list__layout{padding:inherit}.template-selector-item__preview-wrap .components-disabled,.template-selector-item__preview-wrap .components-disabled .editor-styles-wrapper,.template-selector-item__preview-wrap .edit-post-visual-editor,.template-selector-item__preview-wrap .edit-post-visual-editor .editor-styles-wrapper,.template-selector-preview .components-disabled,.template-selector-preview .components-disabled .editor-styles-wrapper,.template-selector-preview .edit-post-visual-editor,.template-selector-preview .edit-post-visual-editor .editor-styles-wrapper{height:100%}.page-template-modal__loading{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);display:flex;align-items:flex-end}.page-template-modal__loading .components-spinner{float:none}.sidebar-modal-opener{display:flex;flex-direction:column;align-items:center;justify-content:center}.sidebar-modal-opener .template-selector-item__label{max-width:300px}.sidebar-modal-opener .template-selector-item__template-title{font-size:1.2rem}.sidebar-modal-opener__button{margin-top:20px}.sidebar-modal-opener__warning-modal{display:flex;flex-direction:column;justify-content:center;align-items:center}.sidebar-modal-opener__warning-text{max-width:300px;font-size:1rem;line-height:1.5rem}.sidebar-modal-opener__warning-options{display:flex;justify-content:space-around;margin-top:20px}
 
trunk/starter-page-templates/dist/starter-page-templates.js DELETED
@@ -1,2 +0,0 @@
1
- /*! For license information please see starter-page-templates.js.LICENSE */
2
- !function(e,t){for(var n in t)e[n]=t[n]}(window,function(e){var t={};function n(r){if(t[r])return t[r].exports;var i=t[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)n.d(r,i,function(t){return e[t]}.bind(null,i));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=33)}([function(e,t){!function(){e.exports=this.wp.element}()},function(e,t){!function(){e.exports=this.lodash}()},function(e,t){!function(){e.exports=this.wp.i18n}()},function(e,t){e.exports=function(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}},function(e,t){!function(){e.exports=this.wp.components}()},function(e,t){e.exports=function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}},function(e,t){!function(){e.exports=this.wp.data}()},function(e,t,n){var r;!function(){"use strict";var n={}.hasOwnProperty;function i(){for(var e=[],t=0;t<arguments.length;t++){var r=arguments[t];if(r){var a=typeof r;if("string"===a||"number"===a)e.push(r);else if(Array.isArray(r)&&r.length){var o=i.apply(null,r);o&&e.push(o)}else if("object"===a)for(var l in r)n.call(r,l)&&r[l]&&e.push(l)}}return e.join(" ")}e.exports?(i.default=i,e.exports=i):void 0===(r=function(){return i}.apply(t,[]))||(e.exports=r)}()},function(e,t){!function(){e.exports=this.wp.compose}()},function(e,t,n){var r=n(3);function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}e.exports=function(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?i(Object(n),!0).forEach((function(t){r(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):i(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}},function(e,t,n){var r=n(26),i=n(27),a=n(28);e.exports=function(e,t){return r(e)||i(e,t)||a()}},function(e,t,n){var r=n(23),i=n(24),a=n(25);e.exports=function(e){return r(e)||i(e)||a()}},function(e,t){e.exports=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}},function(e,t){function n(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}e.exports=function(e,t,r){return t&&n(e.prototype,t),r&&n(e,r),e}},function(e,t,n){var r=n(29),i=n(5);e.exports=function(e,t){return!t||"object"!==r(t)&&"function"!=typeof t?i(e):t}},function(e,t){function n(t){return e.exports=n=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)},n(t)}e.exports=n},function(e,t,n){var r=n(30);e.exports=function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&r(e,t)}},function(e,t){!function(){e.exports=this.wp.blockEditor}()},function(e,t){!function(){e.exports=this.wp.plugins}()},function(e,t){!function(){e.exports=this.wp.editPost}()},function(e,t){!function(){e.exports=this.wp.blocks}()},function(e,t){!function(){e.exports=this.wp.apiFetch}()},function(e,t){!function(){e.exports=this.wp.url}()},function(e,t){e.exports=function(e){if(Array.isArray(e)){for(var t=0,n=new Array(e.length);t<e.length;t++)n[t]=e[t];return n}}},function(e,t){e.exports=function(e){if(Symbol.iterator in Object(e)||"[object Arguments]"===Object.prototype.toString.call(e))return Array.from(e)}},function(e,t){e.exports=function(){throw new TypeError("Invalid attempt to spread non-iterable instance")}},function(e,t){e.exports=function(e){if(Array.isArray(e))return e}},function(e,t){e.exports=function(e,t){if(Symbol.iterator in Object(e)||"[object Arguments]"===Object.prototype.toString.call(e)){var n=[],r=!0,i=!1,a=void 0;try{for(var o,l=e[Symbol.iterator]();!(r=(o=l.next()).done)&&(n.push(o.value),!t||n.length!==t);r=!0);}catch(s){i=!0,a=s}finally{try{r||null==l.return||l.return()}finally{if(i)throw a}}return n}}},function(e,t){e.exports=function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}},function(e,t){function n(t){return"function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?e.exports=n=function(e){return typeof e}:e.exports=n=function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},n(t)}e.exports=n},function(e,t){function n(t,r){return e.exports=n=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e},n(t,r)}e.exports=n},function(e,t){!function(){e.exports=this.wp.nux}()},function(e,t,n){},function(e,t,n){"use strict";n.r(t);var r=n(0),i=n(2),a=n(18),o=n(6),l=n(19),s=n(9),c=n.n(s),p=n(11),u=n.n(p),m=n(10),d=n.n(m),f=n(12),b=n.n(f),g=n(13),O=n.n(g),v=n(14),h=n.n(v),j=n(15),y=n.n(j),_=n(5),w=n.n(_),E=n(16),T=n.n(E),P=n(3),k=n.n(P),S=n(1),x=n(7),N=n.n(x),B=(n(31),n(8)),C=n(4),I=n(20),A=(n(32),n(17)),M=function(e){var t=e.blocks,n=void 0===t?[]:t,i=e.viewportWidth;return n&&n.length?Object(r.createElement)("div",{className:"edit-post-visual-editor"},Object(r.createElement)("div",{className:"editor-styles-wrapper"},Object(r.createElement)("div",{className:"editor-writing-flow"},Object(r.createElement)(A.BlockPreview,{blocks:n,viewportWidth:i})))):null},L=function(e){var t=e.id,n=e.value,i=e.onSelect,a=e.label,o=e.useDynamicPreview,l=void 0!==o&&o,s=e.staticPreviewImg,c=e.staticPreviewImgAlt,p=void 0===c?"":c,u=e.blocks,m=void 0===u?[]:u,d=e.isSelected;if(Object(S.isNil)(t)||Object(S.isNil)(a)||Object(S.isNil)(n))return null;if(l&&(Object(S.isNil)(m)||Object(S.isEmpty)(m)))return null;var f=l?Object(r.createElement)(C.Disabled,null,Object(r.createElement)(M,{blocks:m,viewportWidth:960})):Object(r.createElement)("img",{className:"template-selector-item__media",src:s,alt:p}),b="label-".concat(t,"-").concat(n);return Object(r.createElement)("button",{type:"button",className:N()("template-selector-item__label",{"is-selected":d}),value:n,onClick:function(){i(n)},"aria-labelledby":"".concat(t," ").concat(b)},Object(r.createElement)("div",{className:"template-selector-item__preview-wrap"},f),Object(r.createElement)("span",{className:"template-selector-item__template-title",id:b},a))},D={Address:Object(i._x)("123 Main St","default address","full-site-editing"),Phone:Object(i._x)("555-555-5555","default phone number","full-site-editing"),CompanyName:Object(i._x)("Your Company Name","default company name","full-site-editing"),Vertical:Object(i._x)("Business","default vertical name","full-site-editing")},F={CompanyName:"title",Address:"address",Phone:"phone",Vertical:"vertical"},W=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return e?e.replace(/{{(\w+)}}/g,(function(e,n){var r=D[n];return t[F[n]]||r||n})):""},U=Object(B.compose)(r.memo,B.withInstanceId)((function(e){var t=e.label,n=e.className,i=e.help,a=e.instanceId,o=e.templates,l=void 0===o?[]:o,s=e.blocksByTemplates,c=void 0===s?{}:s,p=e.useDynamicPreview,u=void 0!==p&&p,m=e.onTemplateSelect,d=void 0===m?S.noop:m,f=e.siteInformation,b=void 0===f?{}:f,g=e.selectedTemplate;if(Object(S.isEmpty)(l)||!Object(S.isArray)(l))return null;if(!0===u&&Object(S.isEmpty)(c))return null;var O="template-selector-control-".concat(a);return Object(r.createElement)(C.BaseControl,{label:t,id:O,help:i,className:N()(n,"template-selector-control")},Object(r.createElement)("ul",{className:"template-selector-control__options","data-testid":"template-selector-control-options"},Object(S.map)(l,(function(e){var t=e.slug,n=e.title,a=e.preview,o=e.previewAlt;return Object(r.createElement)("li",{key:"".concat(O,"-").concat(t),className:"template-selector-control__template"},Object(r.createElement)(L,{id:O,value:t,label:W(n,b),help:i,onSelect:d,staticPreviewImg:a,staticPreviewImgAlt:o,blocks:c.hasOwnProperty(t)?c[t]:[],useDynamicPreview:u,isSelected:t===g}))}))))})),R=function(e){var t=e.title,n=e.scale;return(Object(r.createElement)("div",{className:"editor-post-title",style:{transform:"scale(".concat(n,")")}},Object(r.createElement)("div",{className:"wp-block editor-post-title__block"},Object(r.createElement)("textarea",{className:"editor-post-title__input",value:t,onChange:function(){}}))))},q=function(e){return Object(r.createElement)(A.BlockPreview,e)},z=function(e){var t=e.blocks,n=e.viewportWidth,a=e.title,o=Object(r.useRef)(null),l=Object(r.useState)(n),s=d()(l,2),c=s[0],p=s[1],u=Object(r.useState)({scale:1,offset:120}),m=d()(u,2),f=m[0],b=m[1],g=Object(r.useReducer)((function(e){return e+1}),0),O=d()(g,2),v=O[0],h=O[1],j=function(){o&&o.current&&setTimeout((function(){var e=o.current.querySelector(".block-editor-block-preview__content");if(e){var t=parseFloat(Object(S.get)(e,["style","transform"],"").replace("scale(","").replace(")",""));if(t)b({scale:t,offset:120*t})}}),500)},y=Object(r.useCallback)((function(){if(o&&o.current){var e=o.current.clientWidth;p(e>=n?e:n)}}),[n]);return Object(r.useLayoutEffect)((function(){y(),j()}),[t,y]),Object(r.useEffect)((function(){if(t&&t.length){var e=function(){y(),j(),h()},n=Object(S.debounce)(e,300);return window.addEventListener("resize",n),window.jQuery&&window.jQuery(window.document).on("wp-collapse-menu",e),function(){window.removeEventListener("resize",n)}}}),[t,y]),Object(S.isEmpty)(t)||!Object(S.isArray)(t)?Object(r.createElement)("div",{className:N()("template-selector-preview","is-blank-preview")},Object(r.createElement)("div",{className:"template-selector-preview__placeholder"},Object(i.__)("Select a layout to preview.","full-site-editing"))):Object(r.createElement)("div",{className:"template-selector-preview"},Object(r.createElement)(C.Disabled,null,Object(r.createElement)("div",{ref:o,className:"edit-post-visual-editor"},Object(r.createElement)("div",{className:"editor-styles-wrapper"},Object(r.createElement)("div",{className:"editor-writing-flow"},Object(r.createElement)(R,{title:a,scale:f.scale}),Object(r.createElement)("div",{className:"template-selector-preview__offset-correction",style:{top:f.offset}},Object(r.createElement)(q,{key:v,blocks:t,viewportWidth:c})))))))};window._tkq=window._tkq||[];var G=null,Q=function(e,t){G&&window._tkq.push(["recordEvent","a8c_full_site_editing_template_selector_view",{blog_id:G.blogid,segment_id:e,vertical_id:t}])},V=function(e,t){G&&window._tkq.push(["recordEvent","a8c_full_site_editing_template_selector_dismiss",{blog_id:G.blogid,segment_id:e,vertical_id:t}])},H=function(e,t,n){G&&window._tkq.push(["recordEvent","a8c_full_site_editing_template_selector_template_selected",{blog_id:G.blogid,segment_id:e,vertical_id:t,template:n}])},Y=n(21),J=n.n(Y),K=n(22),X=function(e,t,n){var r=e[t=Object(K.removeQueryArgs)(t,"w","s")]||{url:t,usages:[]};return c()({},e,k()({},t,c()({},r,{usages:[].concat(u()(r.usages),u()(n))})))},Z=function e(t,n){switch(t.blocksByClientId[n.clientId]=n,n.name){case"core/cover":case"core/image":var r=n.attributes.url;r&&(t.assets=X(t.assets,r,[{prop:"url",path:[n.clientId,"attributes","url"]},{prop:"id",path:[n.clientId,"attributes","id"]}]));case"core/media-text":var i=n.attributes.mediaUrl;i&&"image"===n.attributes.mediaType&&(t.assets=X(t.assets,i,[{prop:"url",path:[n.clientId,"attributes","mediaUrl"]},{prop:"id",path:[n.clientId,"attributes","mediaId"]}]));case"core/gallery":Object(S.forEach)(n.attributes.images,(function(e,r){t.assets=X(t.assets,e.url,[{prop:"url",path:[n.clientId,"attributes","images",r,"url"]},{prop:"url",path:[n.clientId,"attributes","images",r,"link"]},{prop:"id",path:[n.clientId,"attributes","images",r,"id"]},{prop:"id",path:[n.clientId,"attributes","ids",r]}])}))}return Object(S.isEmpty)(n.innerBlocks)?t:Object(S.reduce)(n.innerBlocks,e,t)},$=function(e){return regeneratorRuntime.async((function(t){for(;;)switch(t.prev=t.next){case 0:return t.next=2,regeneratorRuntime.awrap(J()({method:"POST",path:"/fse/v1/sideload/image/batch",data:{resources:Object(S.map)(e)}}).then((function(t){return Object(S.reduce)(e,(function(e,n){var r=t.shift(),i=r.id,a=r.source_url;return c()({},e,k()({},n.url,{id:i,url:a}))}),{})})));case 2:return t.abrupt("return",t.sent);case 3:case"end":return t.stop()}}))},ee=function(e,t){return Object(S.forEach)(e.assets,(function(n){var r=t[n.url];r&&Object(S.forEach)(n.usages,(function(t){Object(S.set)(e.blocksByClientId,t.path,r[t.prop])}))})),e.blocks},te=function(e){var t;return regeneratorRuntime.async((function(n){for(;;)switch(n.prev=n.next){case 0:if(t=Object(S.reduce)(e,Z,{assets:{},blocksByClientId:{},blocks:e}),!Object(S.isEmpty)(t.assets)){n.next=3;break}return n.abrupt("return",e);case 3:return n.abrupt("return",$(t.assets).then((function(e){return ee(t,e)})));case 4:case"end":return n.stop()}}))},ne="maywood",re=function(e){function t(){var e,n;b()(this,t);for(var a=arguments.length,o=new Array(a),l=0;l<a;l++)o[l]=arguments[l];return n=h()(this,(e=y()(t)).call.apply(e,[this].concat(o))),k()(w()(n),"state",{isLoading:!1,previewedTemplate:null,error:null,isOpen:!1}),k()(w()(n),"getTitlesByTemplateSlugs",Object(S.memoize)((function(e){return Object(S.mapValues)(Object(S.keyBy)(e,"slug"),"title")}))),k()(w()(n),"getBlocksByTemplateSlugs",Object(S.memoize)((function(e){return Object(S.reduce)(e,(function(e,t){var r=t.slug,i=t.content;return e[r]=i?Object(I.parse)(W(i,n.props.siteInformation)):[],e}),{})}))),k()(w()(n),"setTemplate",(function(e){H(n.props.segment.id,n.props.vertical.id,e),n.props.saveTemplateChoice(e);var t=Object(S.find)(n.props.templates,{slug:e,category:"home"}),r=n.getBlocksByTemplateSlug(e),i=t?null:n.getTitleByTemplateSlug(e);r&&r.length?(n.setState({error:null,isLoading:!0}),n.maybePrefetchAssets(r).then((function(e){n.state.isOpen&&(n.props.insertTemplate(i,e),n.setState({isOpen:!1}))})).catch((function(e){n.setState({isLoading:!1,error:e})}))):n.setState({isOpen:!1})})),k()(w()(n),"maybePrefetchAssets",(function(e){return n.props.shouldPrefetchAssets?te(e):Promise.resolve(e)})),k()(w()(n),"handleConfirmation",(function(e){"string"!=typeof e&&(e=n.state.previewedTemplate),n.setTemplate(e),n.props.isPromptedFromSidebar&&n.props.toggleTemplateModal()})),k()(w()(n),"previewTemplate",(function(e){n.setState({previewedTemplate:e}),window.matchMedia("(min-width: 660px)").matches||n.handleConfirmation(e)})),k()(w()(n),"closeModal",(function(e){if(e.target.matches("button.template-selector-item__label"))return!1;V(n.props.segment.id,n.props.vertical.id);var t=Object(S.get)(window,["calypsoifyGutenberg","closeUrl"]);window.top.location=t||"edit.php?post_type=page"})),k()(w()(n),"getTemplateGroups",(function(){var e=Object(S.partition)(n.props.templates,{category:"home"}),t=d()(e,2),r=t[0],i=t[1],a=Object(S.find)(n.props.templates,{slug:n.props.theme})||Object(S.find)(n.props.templates,{slug:ne});if(!n.props.isFrontPage||!a)return{homepageTemplates:Object(S.sortBy)(r,"title"),defaultTemplates:i};var o=Object(S.reject)(r,{slug:a.slug});return{homepageTemplates:[a].concat(u()(Object(S.sortBy)(o,"title"))),defaultTemplates:i}})),k()(w()(n),"renderTemplatesList",(function(e,t){return Object(r.createElement)("fieldset",{className:"page-template-modal__list"},Object(r.createElement)("legend",{className:"page-template-modal__form-title"},t),Object(r.createElement)(U,{label:Object(i.__)("Layout","full-site-editing"),templates:e,blocksByTemplates:n.getBlocksByTemplateSlugs(n.props.templates),onTemplateSelect:n.previewTemplate,useDynamicPreview:!1,siteInformation:n.props.siteInformation,selectedTemplate:n.state.previewedTemplate}))})),n}return T()(t,e),O()(t,[{key:"componentDidMount",value:function(){this.state.isOpen&&Q(this.props.segment.id,this.props.vertical.id)}},{key:"componentDidUpdate",value:function(e,t){!t.isOpen&&this.state.isOpen&&Q(this.props.segment.id,this.props.vertical.id)}},{key:"getBlocksByTemplateSlug",value:function(e){return Object(S.get)(this.getBlocksByTemplateSlugs(this.props.templates),[e],[])}},{key:"getTitleByTemplateSlug",value:function(e){return Object(S.get)(this.getTitlesByTemplateSlugs(this.props.templates),[e],"")}},{key:"render",value:function(){var e=this.state,t=e.previewedTemplate,n=e.isOpen,a=e.isLoading,o=this.props.isPromptedFromSidebar;if(!n)return null;var l=this.getTemplateGroups(),s=l.homepageTemplates,c=l.defaultTemplates;return Object(r.createElement)(C.Modal,{title:Object(i.__)("Select Page Layout","full-site-editing"),className:"page-template-modal",overlayClassName:"page-template-modal-screen-overlay",shouldCloseOnClickOutside:!1,isDismissable:!1,isDismissible:!1},o?Object(r.createElement)(C.IconButton,{className:"page-template-modal__close-button components-icon-button",onClick:this.props.toggleTemplateModal,icon:"no-alt",label:Object(i.__)("Close Layout Selector")}):Object(r.createElement)(C.IconButton,{className:"page-template-modal__close-button components-icon-button",onClick:this.closeModal,icon:"arrow-left-alt2",label:Object(i.__)("Go back")}),Object(r.createElement)("div",{className:"page-template-modal__inner"},a?Object(r.createElement)("div",{className:"page-template-modal__loading"},Object(r.createElement)(C.Spinner,null),Object(i.__)("Adding layout…","full-site-editing")):Object(r.createElement)(r.Fragment,null,Object(r.createElement)("form",{className:"page-template-modal__form"},this.props.isFrontPage?Object(r.createElement)(r.Fragment,null,this.renderTemplatesList(s,Object(i.__)("Recommended Layouts","full-site-editing")),this.renderTemplatesList(c,Object(i.__)("Other Page Layouts","full-site-editing"))):Object(r.createElement)(r.Fragment,null,this.renderTemplatesList(c,Object(i.__)("Recommended Layouts","full-site-editing")),this.renderTemplatesList(s,Object(i.__)("Homepage Layouts","full-site-editing")))),Object(r.createElement)(z,{blocks:this.getBlocksByTemplateSlug(t),viewportWidth:960,title:this.getTitleByTemplateSlug(t)}))),Object(r.createElement)("div",{className:N()("page-template-modal__buttons",{"is-visually-hidden":Object(S.isEmpty)(t)||a})},Object(r.createElement)(C.Button,{isPrimary:!0,isLarge:!0,disabled:Object(S.isEmpty)(t)||a,onClick:this.handleConfirmation},Object(i.sprintf)(Object(i.__)("Use %s layout","full-site-editing"),this.getTitleByTemplateSlug(t)))))}}],[{key:"getDerivedStateFromProps",value:function(e,n){return n.previewedTemplate||Object(S.isEmpty)(e.templates)?null:{isOpen:!0,previewedTemplate:t.getDefaultSelectedTemplate(e)}}}]),t}(r.Component);k()(re,"getDefaultSelectedTemplate",(function(e){var t=Object(S.get)(e.templates,[0,"slug"]),n=e._starter_page_template;if(!e.isFrontPage&&!n)return t;"home"===n&&(n=e.theme);var r=n||e.theme;return Object(S.find)(e.templates,{slug:r})?r:Object(S.find)(e.templates,{slug:ne})?ne:t}));var ie,ae=Object(B.compose)(Object(o.withSelect)((function(e){var t=function(){return e("core/editor").getEditedPostAttribute("meta")},n=t();return{getMeta:t,_starter_page_template:n._starter_page_template,postContentBlock:e("core/editor").getBlocks().find((function(e){return"a8c/post-content"===e.name}))}})),Object(o.withDispatch)((function(e,t){e("core/nux").disableTips();var n=e("core/editor");return{saveTemplateChoice:function(e){var r=t.getMeta();n.editPost({meta:c()({},r,{_starter_page_template:e})})},insertTemplate:function(r,i){r&&n.editPost({title:r});var a=t.postContentBlock;e("core/block-editor").replaceInnerBlocks(a?a.clientId:"",i,!1)}}})))(re),oe=function(e){function t(){var e,n;b()(this,t);for(var r=arguments.length,i=new Array(r),a=0;a<r;a++)i[a]=arguments[a];return n=h()(this,(e=y()(t)).call.apply(e,[this].concat(i))),k()(w()(n),"state",{isTemplateModalOpen:!1,isWarningOpen:!1}),k()(w()(n),"toggleTemplateModal",(function(){n.setState({isTemplateModalOpen:!n.state.isTemplateModalOpen})})),k()(w()(n),"toggleWarningModal",(function(){n.setState({isWarningOpen:!n.state.isWarningOpen})})),k()(w()(n),"getLastTemplateUsed",(function(){var e=n.props,t=e.isFrontPage,r=e.templates,i=e.theme,a=n.props.lastTemplateUsedSlug;if(!a&&t&&(a=i),!a||"blank"===a)return r[0];var o=r.find((function(e){return e.slug===a}));return o||r[0]})),n}return T()(t,e),O()(t,[{key:"render",value:function(){var e=this.getLastTemplateUsed(),t=e.slug,n=e.title,a=e.preview,o=e.previewAlt,l=this.props,s=l.isFrontPage,c=l.templates,p=l.theme,u=l.vertical,m=l.segment,d=l.siteInformation;return Object(r.createElement)("div",{className:"sidebar-modal-opener"},Object(r.createElement)(L,{id:"sidebar-modal-opener__last-template-used-preview",value:t,label:W(n,d),staticPreviewImg:a,staticPreviewImgAlt:o,onSelect:this.toggleWarningModal}),Object(r.createElement)(C.Button,{isPrimary:!0,onClick:this.toggleWarningModal,className:"sidebar-modal-opener__button"},Object(i.__)("Change Layout")),this.state.isTemplateModalOpen&&Object(r.createElement)(ae,{shouldPrefetchAssets:!1,templates:c,theme:p,vertical:u,segment:m,toggleTemplateModal:this.toggleTemplateModal,isFrontPage:s,isPromptedFromSidebar:!0}),this.state.isWarningOpen&&Object(r.createElement)(C.Modal,{title:Object(i.__)("Overwrite Page Content?"),isDismissible:!1,onRequestClose:this.toggleWarningModal,className:"sidebar-modal-opener__warning-modal"},Object(r.createElement)("div",{className:"sidebar-modal-opener__warning-text"},Object(i.__)("Changing the page's layout will remove any customizations or edits you have already made.")),Object(r.createElement)("div",{className:"sidebar-modal-opener__warning-options"},Object(r.createElement)(C.Button,{isDefault:!0,onClick:this.toggleWarningModal},Object(i.__)("Cancel")),Object(r.createElement)(C.Button,{isPrimary:!0,onClick:this.toggleTemplateModal},Object(i.__)("Change Layout")))))}}]),t}(r.Component),le=Object(B.compose)(Object(o.withSelect)((function(e){return{lastTemplateUsedSlug:e("core/editor").getEditedPostAttribute("meta")._starter_page_template}})))(oe),se=window.starterPageTemplatesConfig,ce=se.templates,pe=void 0===ce?[]:ce,ue=se.vertical,me=se.segment,de=se.tracksUserData,fe=se.siteInformation,be=void 0===fe?{}:fe,ge=se.screenAction,Oe=se.theme,ve=se.isFrontPage;de&&(G=ie=de,window._tkq.push(["identifyUser",ie.userid,ie.username])),"add"===ge&&Object(a.registerPlugin)("page-templates",{render:function(){return Object(r.createElement)(ae,{isFrontPage:ve,segment:me,shouldPrefetchAssets:!1,templates:pe,theme:Oe,vertical:ue})}}),Object(a.registerPlugin)("page-templates-sidebar",{render:function(){return Object(r.createElement)(l.PluginDocumentSettingPanel,{name:"Template Modal Opener",title:Object(i.__)("Page Layout"),className:"page-template-modal__sidebar",icon:"none"},Object(r.createElement)(le,{isFrontPage:ve,segment:me,siteInformation:be,templates:pe,theme:Oe,vertical:ue}))}});var he=Object(o.subscribe)((function(){Object(o.select)("core/edit-post").isEditorPanelOpened("page-templates-sidebar/Template Modal Opener")||Object(o.dispatch)("core/edit-post").toggleEditorPanelOpened("page-templates-sidebar/Template Modal Opener"),he()}))}]));
 
 
trunk/starter-page-templates/dist/starter-page-templates.js.LICENSE DELETED
@@ -1,5 +0,0 @@
1
- /*!
2
- Copyright (c) 2017 Jed Watson.
3
- Licensed under the MIT License (MIT), see
4
- http://jedwatson.github.io/classnames
5
- */
 
 
 
 
 
trunk/starter-page-templates/dist/starter-page-templates.rtl.css DELETED
@@ -1 +0,0 @@
1
- .page-template-modal-screen-overlay{animation:none;background-color:transparent;z-index:99}@media screen and (min-width:783px){body:not(.is-fullscreen-mode) .page-template-modal-screen-overlay{right:36px}}@media screen and (min-width:961px){body:not(.is-fullscreen-mode) .page-template-modal-screen-overlay{right:160px}}@media screen and (min-width:783px){body:not(.is-fullscreen-mode).folded .page-template-modal-screen-overlay{right:36px}body:not(.is-fullscreen-mode):not(.folded):not(.auto-fold) .page-template-modal-screen-overlay{right:160px}}body.admin-bar:not(.is-fullscreen-mode) .page-template-modal-screen-overlay{top:46px}@media screen and (min-width:783px){body.admin-bar:not(.is-fullscreen-mode) .page-template-modal-screen-overlay{top:32px}}.page-template-modal{width:100%;height:100vh;animation:none;box-shadow:none;border:none;top:0;right:0;left:0;bottom:0;transform:none;max-width:none;max-height:none;background-color:#eee}.page-template-modal .components-modal__header-heading-container{border:0;clip:rect(1px,1px,1px,1px);-webkit-clip-path:inset(50%);clip-path:inset(50%);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;word-wrap:normal!important}.page-template-modal__close-button{display:block;position:absolute;z-index:20;top:9px;width:36px;height:36px;right:10px}.page-template-modal .components-modal__header:after{display:block;position:absolute;content:" ";border-left:1px solid #e2e4e7;height:100%;right:56px}.page-template-modal .components-modal__content{overflow-y:scroll;-webkit-overflow-scrolling:touch}.page-template-modal__inner{position:relative;margin:0 auto;padding:0 20px 40px}.page-template-modal__list{margin-bottom:20px}.page-template-modal__list .components-base-control__label{border:0;clip:rect(1px,1px,1px,1px);-webkit-clip-path:inset(50%);clip-path:inset(50%);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;word-wrap:normal!important}.template-selector-control__options{display:grid;grid-template-columns:1fr;grid-gap:1.75em}@media screen and (min-width:660px){.template-selector-control__options{margin-top:0;grid-template-columns:repeat(auto-fit,minmax(110px,1fr))}}.template-selector-item__label{display:block;width:100%;font-size:14px;text-align:center;border:2px solid #e2e4e7;border-radius:6px;cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;padding:0;overflow:hidden;background-color:#fff;position:relative;transform:translateZ(0)}.template-selector-item__label .template-selector-item__template-title{width:100%;position:absolute;bottom:0;right:0;height:40px;line-height:40px;background-color:#fff}.template-selector-item__label:focus{box-shadow:0 0 0 1px #fff,0 0 0 3px #00a0d2;outline:2px solid transparent}.template-selector-item__label:hover{border:2px solid #c9c9ca}.template-selector-item__label.is-selected{border:2px solid #555d66;outline:2px solid transparent;outline-offset:-2px}.template-selector-item__label.is-selected:focus{box-shadow:0 0 0 1px #fff,0 0 0 3px #00a0d2;border:2px solid #555d66;outline:4px solid transparent;outline-offset:-4px}.template-selector-item__preview-wrap{width:100%;display:block;margin:0 auto;background:#fff;border-radius:0;overflow:hidden;height:0;padding-top:120%;box-sizing:content-box;position:relative;pointer-events:none;opacity:1;transform:translateZ(0)}@media screen and (min-width:660px){.template-selector-item__preview-wrap{padding-top:100%}}.template-selector-item__preview-wrap.is-rendering{opacity:.5}.template-selector-item__preview-wrap .block-editor-block-list__block,.template-selector-item__preview-wrap .block-editor-block-list__layout{padding:inherit}.template-selector-item__media{width:100%;display:block;position:absolute;top:0;right:0}@media screen and (max-width:659px){.template-selector-control__template:first-child .template-selector-item__preview-wrap{padding-top:0;height:70px}.template-selector-control__template:first-child .template-selector-item__template-title{height:70px;line-height:70px}}@media screen and (min-width:660px){.page-template-modal__form{max-width:20%}}@media screen and (min-width:783px){.page-template-modal__form{max-width:30%}}.page-template-modal__form-title{font-weight:700;margin-bottom:1em;text-align:center}@media screen and (min-width:660px){.page-template-modal__form-title{text-align:right}}.page-template-modal__buttons{position:absolute;left:0;top:0;z-index:10;height:56px;display:flex;align-items:center;padding-left:24px}@media screen and (min-width:660px){.page-template-modal__buttons{display:flex}}.page-template-modal__buttons.is-visually-hidden{border:0;clip:rect(1px,1px,1px,1px);-webkit-clip-path:inset(50%);clip-path:inset(50%);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;word-wrap:normal!important}.page-template-modal__buttons .components-button{height:33px;line-height:32px}.template-selector-preview{display:none;position:fixed;top:157px;bottom:24px;right:calc(20% + 48px);left:24px;background:#fff;border-radius:2px;overflow-x:hidden;overflow-y:auto;box-shadow:0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.12),0 1px 5px 0 rgba(0,0,0,.2)}@media screen and (min-width:660px){.template-selector-preview{display:block}.template-selector-preview.is-blank-preview{align-items:center;display:flex;justify-content:center}}@media screen and (min-width:783px){.template-selector-preview{top:143px;right:calc(30% + 72px)}body:not(.auto-fold):not(.folded) .template-selector-preview{right:calc(30% + 172px)}}@media screen and (min-width:961px){.template-selector-preview{right:calc(30% + 172px)}body.folded .template-selector-preview{right:calc(30% + 72px)}}body.is-fullscreen-mode .template-selector-preview{top:111px}@media screen and (min-width:783px){body.is-fullscreen-mode .template-selector-preview{right:calc(30% + 48px)!important}}.template-selector-preview .edit-post-visual-editor{margin:0;padding:0}.template-selector-preview .editor-styles-wrapper .template-selector-preview__offset-correction{position:relative;top:120px}.template-selector-preview .editor-styles-wrapper .editor-post-title{transform-origin:top center;width:100%;display:block;position:absolute;top:0}.template-selector-preview .editor-styles-wrapper .editor-post-title,.template-selector-preview .editor-styles-wrapper .editor-post-title__block,.template-selector-preview .editor-styles-wrapper .editor-post-title__input{padding-top:0;padding-bottom:0;margin-top:0;margin-bottom:0}.template-selector-preview .editor-styles-wrapper .editor-post-title .editor-post-title__input,.template-selector-preview .editor-styles-wrapper .editor-post-title__block .editor-post-title__input,.template-selector-preview .editor-styles-wrapper .editor-post-title__input .editor-post-title__input{margin:0;padding:0;height:120px;line-height:120px;overflow:hidden;resize:none}.template-selector-preview__placeholder{color:var(--color-text-subtle);font-size:15px;font-weight:400}.block-editor-block-preview__container .editor-styles-wrapper .wp-block{width:100%}.block-editor-block-preview__container .editor-styles-wrapper .wp-block[data-type="core/cover"][data-align=full]{margin:0}.block-editor-block-preview__container .editor-styles-wrapper .wp-block[data-type="core/cover"][data-align=full] .wp-block-cover{padding:0}.block-editor-block-preview__container .editor-styles-wrapper .wp-block-columns>.editor-inner-blocks>.editor-block-list__layout>[data-type="core/column"]>.editor-block-list__block-edit>div>.block-core-columns>.editor-inner-blocks{margin-top:0;margin-bottom:0}.block-editor-block-preview__container .editor-styles-wrapper .block-editor-block-list__block[data-align=full]{margin:0}@media screen and (min-width:600px){.block-editor-block-preview__container .editor-styles-wrapper .block-editor-block-list__block .block-editor-block-list__block-edit{margin:0}}.block-editor-block-preview__container .editor-styles-wrapper .block-editor-block-list__block,.block-editor-block-preview__container .editor-styles-wrapper .block-editor-block-list__layout{padding:inherit}.template-selector-item__preview-wrap .components-disabled,.template-selector-item__preview-wrap .components-disabled .editor-styles-wrapper,.template-selector-item__preview-wrap .edit-post-visual-editor,.template-selector-item__preview-wrap .edit-post-visual-editor .editor-styles-wrapper,.template-selector-preview .components-disabled,.template-selector-preview .components-disabled .editor-styles-wrapper,.template-selector-preview .edit-post-visual-editor,.template-selector-preview .edit-post-visual-editor .editor-styles-wrapper{height:100%}.page-template-modal__loading{position:absolute;top:50%;right:50%;transform:translate(50%,-50%);display:flex;align-items:flex-end}.page-template-modal__loading .components-spinner{float:none}.sidebar-modal-opener{display:flex;flex-direction:column;align-items:center;justify-content:center}.sidebar-modal-opener .template-selector-item__label{max-width:300px}.sidebar-modal-opener .template-selector-item__template-title{font-size:1.2rem}.sidebar-modal-opener__button{margin-top:20px}.sidebar-modal-opener__warning-modal{display:flex;flex-direction:column;justify-content:center;align-items:center}.sidebar-modal-opener__warning-text{max-width:300px;font-size:1rem;line-height:1.5rem}.sidebar-modal-opener__warning-options{display:flex;justify-content:space-around;margin-top:20px}
 
trunk/starter-page-templates/index.js DELETED
@@ -1,87 +0,0 @@
1
- /* eslint-disable import/no-extraneous-dependencies */
2
- /**
3
- * External dependencies
4
- */
5
- import { __ } from '@wordpress/i18n';
6
- import { registerPlugin } from '@wordpress/plugins';
7
- import { select, dispatch, subscribe } from '@wordpress/data';
8
- import { PluginDocumentSettingPanel } from '@wordpress/edit-post';
9
-
10
- /**
11
- * Internal dependencies
12
- */
13
- import { PageTemplatesPlugin } from './page-template-modal';
14
- import SidebarTemplatesPlugin from './page-template-modal/components/sidebar-modal-opener';
15
- import { initializeWithIdentity } from './page-template-modal/utils/tracking';
16
- /* eslint-enable import/no-extraneous-dependencies */
17
-
18
- // Load config passed from backend.
19
- const {
20
- templates = [],
21
- vertical,
22
- segment,
23
- tracksUserData,
24
- siteInformation = {},
25
- screenAction,
26
- theme,
27
- isFrontPage,
28
- } = window.starterPageTemplatesConfig;
29
-
30
- if ( tracksUserData ) {
31
- initializeWithIdentity( tracksUserData );
32
- }
33
-
34
- // Open plugin only if we are creating new page.
35
- if ( screenAction === 'add' ) {
36
- registerPlugin( 'page-templates', {
37
- render: () => {
38
- return (
39
- <PageTemplatesPlugin
40
- isFrontPage={ isFrontPage }
41
- segment={ segment }
42
- shouldPrefetchAssets={ false }
43
- templates={ templates }
44
- theme={ theme }
45
- vertical={ vertical }
46
- />
47
- );
48
- },
49
- } );
50
- }
51
-
52
- // Always register ability to open from document sidebar.
53
- registerPlugin( 'page-templates-sidebar', {
54
- render: () => {
55
- return (
56
- <PluginDocumentSettingPanel
57
- name="Template Modal Opener"
58
- title={ __( 'Page Layout' ) }
59
- className="page-template-modal__sidebar" // eslint-disable-line wpcalypso/jsx-classname-namespace
60
- icon="none"
61
- >
62
- <SidebarTemplatesPlugin
63
- isFrontPage={ isFrontPage }
64
- segment={ segment }
65
- siteInformation={ siteInformation }
66
- templates={ templates }
67
- theme={ theme }
68
- vertical={ vertical }
69
- />
70
- </PluginDocumentSettingPanel>
71
- );
72
- },
73
- } );
74
-
75
- // Make sidebar plugin open by default.
76
- const unsubscribe = subscribe( () => {
77
- if (
78
- ! select( 'core/edit-post' ).isEditorPanelOpened(
79
- 'page-templates-sidebar/Template Modal Opener'
80
- )
81
- ) {
82
- dispatch( 'core/edit-post' ).toggleEditorPanelOpened(
83
- 'page-templates-sidebar/Template Modal Opener'
84
- );
85
- }
86
- unsubscribe();
87
- } );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/starter-page-templates/page-template-modal/components/block-preview.js DELETED
@@ -1,27 +0,0 @@
1
- /**
2
- * External dependencies
3
- */
4
-
5
- /**
6
- * Internal dependencies
7
- */
8
-
9
- /**
10
- * WordPress dependencies
11
- */
12
- /* eslint-disable import/no-extraneous-dependencies */
13
- import { BlockPreview } from '@wordpress/block-editor';
14
- /* eslint-enable import/no-extraneous-dependencies */
15
-
16
- // Exists as a pass through component to simplying testing
17
- // components which consume `BlockPreview` from
18
- // `@wordpress/block-editor`. This is because jest cannot mock
19
- // node modules that are not part of the root node modules.
20
- // Due to the way this projects dependencies are defined
21
- // `@wordpress/block-editor` does not exist within `node_modules`
22
- // and it is there impossible to mock it without providing a wrapping
23
- // component to act as a pass though.
24
- // See https://jestjs.io/docs/en/manual-mocks
25
- export default function( props ) {
26
- return <BlockPreview { ...props } />;
27
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/starter-page-templates/page-template-modal/components/block-template-preview.js DELETED
@@ -1,34 +0,0 @@
1
- /**
2
- * External dependencies
3
- */
4
-
5
- /**
6
- * Internal dependencies
7
- */
8
-
9
- /**
10
- * WordPress dependencies
11
- */
12
- /* eslint-disable import/no-extraneous-dependencies */
13
- import { BlockPreview } from '@wordpress/block-editor';
14
- /* eslint-enable import/no-extraneous-dependencies */
15
-
16
- const BlockTemplatePreview = ( { blocks = [], viewportWidth } ) => {
17
- if ( ! blocks || ! blocks.length ) {
18
- return null;
19
- }
20
-
21
- return (
22
- /* eslint-disable wpcalypso/jsx-classname-namespace */
23
- <div className="edit-post-visual-editor">
24
- <div className="editor-styles-wrapper">
25
- <div className="editor-writing-flow">
26
- <BlockPreview blocks={ blocks } viewportWidth={ viewportWidth } />
27
- </div>
28
- </div>
29
- </div>
30
- /* eslint-enable wpcalypso/jsx-classname-namespace */
31
- );
32
- };
33
-
34
- export default BlockTemplatePreview;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/starter-page-templates/page-template-modal/components/preview-template-title.js DELETED
@@ -1,22 +0,0 @@
1
- /**
2
- * Return a component which acts as a PostTitle,
3
- * applying the css classes needed to follow the styles
4
- * inherited from the Editor.
5
- *
6
- * @param {object} props Component props.
7
- * @param {string} props.title Template title - transform css rule.
8
- * @param {number} props.scale Scale transform based upon the preview viewport width.
9
- * @returns {*} Component
10
- */
11
-
12
- const PreviewTemplateTitle = ( { title, scale } ) => (
13
- /* eslint-disable wpcalypso/jsx-classname-namespace */
14
- <div className="editor-post-title" style={ { transform: `scale(${ scale })` } }>
15
- <div className="wp-block editor-post-title__block">
16
- <textarea className="editor-post-title__input" value={ title } onChange={ () => {} } />
17
- </div>
18
- </div>
19
- /* eslint-enable wpcalypso/jsx-classname-namespace */
20
- );
21
-
22
- export default PreviewTemplateTitle;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/starter-page-templates/page-template-modal/components/sidebar-modal-opener.js DELETED
@@ -1,124 +0,0 @@
1
- /* eslint-disable import/no-extraneous-dependencies */
2
-
3
- /**
4
- * External dependencies
5
- */
6
- import { Component } from '@wordpress/element';
7
- import { withSelect } from '@wordpress/data';
8
- import { Button, Modal } from '@wordpress/components';
9
- import { compose } from '@wordpress/compose';
10
- import { __ } from '@wordpress/i18n';
11
- /**
12
- * Internal dependencies
13
- */
14
- import { PageTemplatesPlugin } from '../index';
15
- import TemplateSelectorItem from './template-selector-item';
16
- import replacePlaceholders from '../utils/replace-placeholders';
17
- /* eslint-enable import/no-extraneous-dependencies */
18
- class SidebarModalOpener extends Component {
19
- state = {
20
- isTemplateModalOpen: false,
21
- isWarningOpen: false,
22
- };
23
-
24
- toggleTemplateModal = () => {
25
- this.setState( { isTemplateModalOpen: ! this.state.isTemplateModalOpen } );
26
- };
27
-
28
- toggleWarningModal = () => {
29
- this.setState( { isWarningOpen: ! this.state.isWarningOpen } );
30
- };
31
-
32
- getLastTemplateUsed = () => {
33
- const { isFrontPage, templates, theme } = this.props;
34
- let { lastTemplateUsedSlug } = this.props;
35
- // Try to match the homepage of the theme. Note that as folks transition
36
- // to using the slug-based version of the homepage (e.g. "shawburn"), the
37
- // slug will work normally without going through this check.
38
- if ( ! lastTemplateUsedSlug && isFrontPage ) {
39
- lastTemplateUsedSlug = theme;
40
- }
41
-
42
- if ( ! lastTemplateUsedSlug || lastTemplateUsedSlug === 'blank' ) {
43
- // If no template used or 'blank', preview any other template (1 is currently 'Home' template).
44
- return templates[ 0 ];
45
- }
46
- const matchingTemplate = templates.find( temp => temp.slug === lastTemplateUsedSlug );
47
- // If no matching template, return the blank template.
48
- if ( ! matchingTemplate ) {
49
- return templates[ 0 ];
50
- }
51
- return matchingTemplate;
52
- };
53
-
54
- render() {
55
- const { slug, title, preview, previewAlt } = this.getLastTemplateUsed();
56
- const { isFrontPage, templates, theme, vertical, segment, siteInformation } = this.props;
57
-
58
- return (
59
- <div className="sidebar-modal-opener">
60
- <TemplateSelectorItem
61
- id="sidebar-modal-opener__last-template-used-preview"
62
- value={ slug }
63
- label={ replacePlaceholders( title, siteInformation ) }
64
- staticPreviewImg={ preview }
65
- staticPreviewImgAlt={ previewAlt }
66
- onSelect={ this.toggleWarningModal }
67
- />
68
-
69
- <Button
70
- isPrimary
71
- onClick={ this.toggleWarningModal }
72
- className="sidebar-modal-opener__button"
73
- >
74
- { __( 'Change Layout' ) }
75
- </Button>
76
-
77
- { this.state.isTemplateModalOpen && (
78
- <PageTemplatesPlugin
79
- shouldPrefetchAssets={ false }
80
- templates={ templates }
81
- theme={ theme }
82
- vertical={ vertical }
83
- segment={ segment }
84
- toggleTemplateModal={ this.toggleTemplateModal }
85
- isFrontPage={ isFrontPage }
86
- isPromptedFromSidebar
87
- />
88
- ) }
89
-
90
- { this.state.isWarningOpen && (
91
- <Modal
92
- title={ __( 'Overwrite Page Content?' ) }
93
- isDismissible={ false }
94
- onRequestClose={ this.toggleWarningModal }
95
- className="sidebar-modal-opener__warning-modal"
96
- >
97
- <div className="sidebar-modal-opener__warning-text">
98
- { __(
99
- `Changing the page's layout will remove any customizations or edits you have already made.`
100
- ) }
101
- </div>
102
- <div className="sidebar-modal-opener__warning-options">
103
- <Button isDefault onClick={ this.toggleWarningModal }>
104
- { __( 'Cancel' ) }
105
- </Button>
106
- <Button isPrimary onClick={ this.toggleTemplateModal }>
107
- { __( 'Change Layout' ) }
108
- </Button>
109
- </div>
110
- </Modal>
111
- ) }
112
- </div>
113
- );
114
- }
115
- }
116
-
117
- const SidebarTemplatesPlugin = compose(
118
- withSelect( select => ( {
119
- lastTemplateUsedSlug: select( 'core/editor' ).getEditedPostAttribute( 'meta' )
120
- ._starter_page_template,
121
- } ) )
122
- )( SidebarModalOpener );
123
-
124
- export default SidebarTemplatesPlugin;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/starter-page-templates/page-template-modal/components/template-selector-control.js DELETED
@@ -1,78 +0,0 @@
1
- /**
2
- * External dependencies
3
- */
4
- /* eslint-disable import/no-extraneous-dependencies */
5
- import { isEmpty, isArray, noop, map } from 'lodash';
6
- /* eslint-enable import/no-extraneous-dependencies */
7
- import classnames from 'classnames';
8
-
9
- /**
10
- * WordPress dependencies
11
- */
12
- /* eslint-disable import/no-extraneous-dependencies */
13
- import { withInstanceId, compose } from '@wordpress/compose';
14
- import { BaseControl } from '@wordpress/components';
15
- import { memo } from '@wordpress/element';
16
- /* eslint-enable import/no-extraneous-dependencies */
17
-
18
- /**
19
- * Internal dependencies
20
- */
21
- import TemplateSelectorItem from './template-selector-item';
22
- import replacePlaceholders from '../utils/replace-placeholders';
23
-
24
- export const TemplateSelectorControl = ( {
25
- label,
26
- className,
27
- help,
28
- instanceId,
29
- templates = [],
30
- blocksByTemplates = {},
31
- useDynamicPreview = false,
32
- onTemplateSelect = noop,
33
- siteInformation = {},
34
- selectedTemplate,
35
- } ) => {
36
- if ( isEmpty( templates ) || ! isArray( templates ) ) {
37
- return null;
38
- }
39
-
40
- if ( true === useDynamicPreview && isEmpty( blocksByTemplates ) ) {
41
- return null;
42
- }
43
-
44
- const id = `template-selector-control-${ instanceId }`;
45
-
46
- return (
47
- <BaseControl
48
- label={ label }
49
- id={ id }
50
- help={ help }
51
- className={ classnames( className, 'template-selector-control' ) }
52
- >
53
- <ul
54
- className="template-selector-control__options"
55
- data-testid="template-selector-control-options"
56
- >
57
- { map( templates, ( { slug, title, preview, previewAlt } ) => (
58
- <li key={ `${ id }-${ slug }` } className="template-selector-control__template">
59
- <TemplateSelectorItem
60
- id={ id }
61
- value={ slug }
62
- label={ replacePlaceholders( title, siteInformation ) }
63
- help={ help }
64
- onSelect={ onTemplateSelect }
65
- staticPreviewImg={ preview }
66
- staticPreviewImgAlt={ previewAlt }
67
- blocks={ blocksByTemplates.hasOwnProperty( slug ) ? blocksByTemplates[ slug ] : [] }
68
- useDynamicPreview={ useDynamicPreview }
69
- isSelected={ slug === selectedTemplate }
70
- />
71
- </li>
72
- ) ) }
73
- </ul>
74
- </BaseControl>
75
- );
76
- };
77
-
78
- export default compose( memo, withInstanceId )( TemplateSelectorControl );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/starter-page-templates/page-template-modal/components/template-selector-item.js DELETED
@@ -1,75 +0,0 @@
1
- /**
2
- * External dependencies
3
- */
4
- /* eslint-disable import/no-extraneous-dependencies */
5
- import { isNil, isEmpty } from 'lodash';
6
- /* eslint-enable import/no-extraneous-dependencies */
7
- import classnames from 'classnames';
8
-
9
- /**
10
- * WordPress dependencies
11
- */
12
- import BlockPreview from './block-template-preview';
13
- /* eslint-disable import/no-extraneous-dependencies */
14
- import { Disabled } from '@wordpress/components';
15
- /* eslint-enable import/no-extraneous-dependencies */
16
-
17
- const TemplateSelectorItem = props => {
18
- const {
19
- id,
20
- value,
21
- onSelect,
22
- label,
23
- useDynamicPreview = false,
24
- staticPreviewImg,
25
- staticPreviewImgAlt = '',
26
- blocks = [],
27
- isSelected,
28
- } = props;
29
-
30
- if ( isNil( id ) || isNil( label ) || isNil( value ) ) {
31
- return null;
32
- }
33
-
34
- if ( useDynamicPreview && ( isNil( blocks ) || isEmpty( blocks ) ) ) {
35
- return null;
36
- }
37
-
38
- // Define static or dynamic preview.
39
- const innerPreview = useDynamicPreview ? (
40
- <Disabled>
41
- <BlockPreview blocks={ blocks } viewportWidth={ 960 } />
42
- </Disabled>
43
- ) : (
44
- <img
45
- className="template-selector-item__media"
46
- src={ staticPreviewImg }
47
- alt={ staticPreviewImgAlt }
48
- />
49
- );
50
-
51
- const labelId = `label-${ id }-${ value }`;
52
-
53
- const handleLabelClick = () => {
54
- onSelect( value );
55
- };
56
-
57
- return (
58
- <button
59
- type="button"
60
- className={ classnames( 'template-selector-item__label', {
61
- 'is-selected': isSelected,
62
- } ) }
63
- value={ value }
64
- onClick={ handleLabelClick }
65
- aria-labelledby={ `${ id } ${ labelId }` }
66
- >
67
- <div className="template-selector-item__preview-wrap">{ innerPreview }</div>
68
- <span className="template-selector-item__template-title" id={ labelId }>
69
- { label }
70
- </span>
71
- </button>
72
- );
73
- };
74
-
75
- export default TemplateSelectorItem;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/starter-page-templates/page-template-modal/components/template-selector-preview.js DELETED
@@ -1,145 +0,0 @@
1
- /**
2
- * External dependencies
3
- */
4
- /* eslint-disable import/no-extraneous-dependencies */
5
- import { debounce, get, isArray, isEmpty } from 'lodash';
6
- /* eslint-enable import/no-extraneous-dependencies */
7
- import classnames from 'classnames';
8
-
9
- /**
10
- * WordPress dependencies
11
- */
12
- /* eslint-disable import/no-extraneous-dependencies */
13
- import { __ } from '@wordpress/i18n';
14
- import { Disabled } from '@wordpress/components';
15
- import {
16
- useState,
17
- useEffect,
18
- useLayoutEffect,
19
- useRef,
20
- useReducer,
21
- useCallback,
22
- } from '@wordpress/element';
23
- /* eslint-enable import/no-extraneous-dependencies */
24
-
25
- /**
26
- * Internal dependencies
27
- */
28
- import PreviewTemplateTitle from './preview-template-title';
29
- import BlockPreview from './block-preview';
30
-
31
- const TemplateSelectorPreview = ( { blocks, viewportWidth, title } ) => {
32
- const THRESHOLD_RESIZE = 300;
33
- const TITLE_DEFAULT_HEIGHT = 120;
34
-
35
- const ref = useRef( null );
36
-
37
- const [ previewViewport, setPreviewViewport ] = useState( viewportWidth );
38
- const [ titleTransform, setTitleTransform ] = useState( {
39
- scale: 1,
40
- offset: TITLE_DEFAULT_HEIGHT,
41
- } );
42
- const [ recompute, triggerRecompute ] = useReducer( state => state + 1, 0 );
43
-
44
- const updatePreviewTitle = () => {
45
- if ( ! ref || ! ref.current ) {
46
- return;
47
- }
48
-
49
- setTimeout( () => {
50
- const preview = ref.current.querySelector( '.block-editor-block-preview__content' );
51
- if ( ! preview ) {
52
- return;
53
- }
54
-
55
- const previewScale = parseFloat(
56
- get( preview, [ 'style', 'transform' ], '' )
57
- .replace( 'scale(', '' )
58
- .replace( ')', '' )
59
- );
60
- if ( previewScale ) {
61
- const titleOffset = TITLE_DEFAULT_HEIGHT * previewScale;
62
- setTitleTransform( { scale: previewScale, offset: titleOffset } );
63
- }
64
- }, 500 );
65
- };
66
-
67
- const updatePreviewViewport = useCallback( () => {
68
- if ( ! ref || ! ref.current ) {
69
- return;
70
- }
71
- const wrapperWidth = ref.current.clientWidth;
72
- if ( wrapperWidth >= viewportWidth ) {
73
- setPreviewViewport( wrapperWidth );
74
- } else {
75
- setPreviewViewport( viewportWidth );
76
- }
77
- }, [ viewportWidth ] );
78
-
79
- useLayoutEffect( () => {
80
- updatePreviewViewport();
81
- updatePreviewTitle();
82
- }, [ blocks, updatePreviewViewport ] );
83
-
84
- useEffect( () => {
85
- if ( ! blocks || ! blocks.length ) {
86
- return;
87
- }
88
-
89
- const rePreviewTemplate = () => {
90
- updatePreviewViewport();
91
- updatePreviewTitle();
92
- triggerRecompute();
93
- };
94
-
95
- const refreshPreview = debounce( rePreviewTemplate, THRESHOLD_RESIZE );
96
- window.addEventListener( 'resize', refreshPreview );
97
-
98
- // In wp-admin, listen to the jQuery `wp-collapse-menu` event to refresh the preview on sidebar toggle.
99
- if ( window.jQuery ) {
100
- window.jQuery( window.document ).on( 'wp-collapse-menu', rePreviewTemplate );
101
- }
102
-
103
- return () => {
104
- window.removeEventListener( 'resize', refreshPreview );
105
- };
106
- }, [ blocks, updatePreviewViewport ] );
107
-
108
- if ( isEmpty( blocks ) || ! isArray( blocks ) ) {
109
- return (
110
- <div className={ classnames( 'template-selector-preview', 'is-blank-preview' ) }>
111
- <div className="template-selector-preview__placeholder">
112
- { __( 'Select a layout to preview.', 'full-site-editing' ) }
113
- </div>
114
- </div>
115
- );
116
- }
117
-
118
- return (
119
- /* eslint-disable wpcalypso/jsx-classname-namespace */
120
- <div className="template-selector-preview">
121
- <Disabled>
122
- <div ref={ ref } className="edit-post-visual-editor">
123
- <div className="editor-styles-wrapper">
124
- <div className="editor-writing-flow">
125
- <PreviewTemplateTitle title={ title } scale={ titleTransform.scale } />
126
- <div
127
- className="template-selector-preview__offset-correction"
128
- style={ { top: titleTransform.offset } }
129
- >
130
- <BlockPreview
131
- key={ recompute }
132
- blocks={ blocks }
133
- viewportWidth={ previewViewport }
134
- />
135
- </div>
136
- </div>
137
- </div>
138
- </div>
139
- </Disabled>
140
- </div>
141
- /* eslint-enable wpcalypso/jsx-classname-namespace */
142
- );
143
- };
144
-
145
- export default TemplateSelectorPreview;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/starter-page-templates/page-template-modal/components/test/__snapshots__/template-selector-control-test.js.snap DELETED
@@ -1,128 +0,0 @@
1
- // Jest Snapshot v1, https://goo.gl/fbAQLP
2
-
3
- exports[`TemplateSelectorControl Basic rendering renders with required props 1`] = `
4
- <div>
5
- <div
6
- class="components-base-control template-selector-control"
7
- >
8
- <div
9
- class="components-base-control__field"
10
- >
11
- <label
12
- class="components-base-control__label"
13
- for="template-selector-control-17"
14
- >
15
- Select a Template...
16
- </label>
17
- <ul
18
- class="template-selector-control__options"
19
- data-testid="template-selector-control-options"
20
- >
21
- <li
22
- class="template-selector-control__template"
23
- >
24
- <button
25
- aria-labelledby="template-selector-control-17 label-template-selector-control-17-blank"
26
- class="template-selector-item__label"
27
- type="button"
28
- value="blank"
29
- >
30
- <div
31
- class="template-selector-item__preview-wrap"
32
- >
33
- <img
34
- alt=""
35
- class="template-selector-item__media"
36
- />
37
- </div>
38
- <span
39
- class="template-selector-item__template-title"
40
- id="label-template-selector-control-17-blank"
41
- >
42
- Blank
43
- </span>
44
- </button>
45
- </li>
46
- <li
47
- class="template-selector-control__template"
48
- >
49
- <button
50
- aria-labelledby="template-selector-control-17 label-template-selector-control-17-template-1"
51
- class="template-selector-item__label"
52
- type="button"
53
- value="template-1"
54
- >
55
- <div
56
- class="template-selector-item__preview-wrap"
57
- >
58
- <img
59
- alt="Testing alt"
60
- class="template-selector-item__media"
61
- src="https://via.placeholder.com/350x150"
62
- />
63
- </div>
64
- <span
65
- class="template-selector-item__template-title"
66
- id="label-template-selector-control-17-template-1"
67
- >
68
- Template 1
69
- </span>
70
- </button>
71
- </li>
72
- <li
73
- class="template-selector-control__template"
74
- >
75
- <button
76
- aria-labelledby="template-selector-control-17 label-template-selector-control-17-template-2"
77
- class="template-selector-item__label"
78
- type="button"
79
- value="template-2"
80
- >
81
- <div
82
- class="template-selector-item__preview-wrap"
83
- >
84
- <img
85
- alt="Testing alt 2"
86
- class="template-selector-item__media"
87
- src="https://via.placeholder.com/300x250"
88
- />
89
- </div>
90
- <span
91
- class="template-selector-item__template-title"
92
- id="label-template-selector-control-17-template-2"
93
- >
94
- Template 2
95
- </span>
96
- </button>
97
- </li>
98
- <li
99
- class="template-selector-control__template"
100
- >
101
- <button
102
- aria-labelledby="template-selector-control-17 label-template-selector-control-17-template-3"
103
- class="template-selector-item__label"
104
- type="button"
105
- value="template-3"
106
- >
107
- <div
108
- class="template-selector-item__preview-wrap"
109
- >
110
- <img
111
- alt="Testing alt 3"
112
- class="template-selector-item__media"
113
- src="https://via.placeholder.com/500x200"
114
- />
115
- </div>
116
- <span
117
- class="template-selector-item__template-title"
118
- id="label-template-selector-control-17-template-3"
119
- >
120
- Template 3
121
- </span>
122
- </button>
123
- </li>
124
- </ul>
125
- </div>
126
- </div>
127
- </div>
128
- `;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/starter-page-templates/page-template-modal/components/test/__snapshots__/template-selector-preview-test.js.snap DELETED
@@ -1,48 +0,0 @@
1
- // Jest Snapshot v1, https://goo.gl/fbAQLP
2
-
3
- exports[`TemplateSelectorPreview Basic rendering renders the preview when blocks are provided 1`] = `
4
- <div>
5
- <div
6
- class="template-selector-preview"
7
- >
8
- <div
9
- class="components-disabled"
10
- >
11
- <div
12
- class="edit-post-visual-editor"
13
- >
14
- <div
15
- class="editor-styles-wrapper"
16
- >
17
- <div
18
- class="editor-writing-flow"
19
- >
20
- <div
21
- class="editor-post-title"
22
- style="transform: scale(1);"
23
- >
24
- <div
25
- class="wp-block editor-post-title__block"
26
- >
27
- <textarea
28
- class="editor-post-title__input"
29
- />
30
- </div>
31
- </div>
32
- <div
33
- class="template-selector-preview__offset-correction"
34
- style="top: 120px;"
35
- >
36
- <div
37
- data-testid="block-template-preview"
38
- >
39
- MockedBlockPreview
40
- </div>
41
- </div>
42
- </div>
43
- </div>
44
- </div>
45
- </div>
46
- </div>
47
- </div>
48
- `;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/starter-page-templates/page-template-modal/components/test/helpers/templates-blocks-helpers.js DELETED
@@ -1,58 +0,0 @@
1
- /**
2
- * External dependencies
3
- */
4
- /* eslint-disable import/no-extraneous-dependencies */
5
- import { uniqueId, range, toArray } from 'lodash';
6
- /* eslint-enable import/no-extraneous-dependencies */
7
-
8
- export const templatesFixture = [
9
- {
10
- slug: 'blank',
11
- title: 'Blank',
12
- },
13
- {
14
- slug: 'template-1',
15
- title: 'Template 1',
16
- preview: 'https://via.placeholder.com/350x150',
17
- previewAlt: 'Testing alt',
18
- },
19
- {
20
- slug: 'template-2',
21
- title: 'Template 2',
22
- preview: 'https://via.placeholder.com/300x250',
23
- previewAlt: 'Testing alt 2',
24
- },
25
- {
26
- slug: 'template-3',
27
- title: 'Template 3',
28
- preview: 'https://via.placeholder.com/500x200',
29
- previewAlt: 'Testing alt 3',
30
- },
31
- ];
32
-
33
- export const blocksByTemplatesFixture = templatesFixture.reduce( ( acc, curr ) => {
34
- acc[ curr.slug ] = range( 4 ).map( () => {
35
- return {
36
- clientId: uniqueId(),
37
- name: 'core/paragraph',
38
- isValid: true,
39
- attributes: {
40
- align: 'left',
41
- content:
42
- 'Visitors will want to know who is on the other side of the page. Use this space to write about yourself, your site, your business, or anything you want. Use the testimonials below to quote others, talking about the same thing – in their own words.',
43
- dropCap: false,
44
- fontWeight: '',
45
- textTransform: '',
46
- noBottomSpacing: false,
47
- noTopSpacing: false,
48
- coblocks: [],
49
- },
50
- innerBlocks: [],
51
- originalContent:
52
- '<p style="text-align:left;">Visitors will want to know who is on the other side of the page. Use this space to write about yourself, your site, your business, or anything you want. Use the testimonials below to quote others, talking about the same thing – in their own words.</p>',
53
- };
54
- } );
55
- return acc;
56
- }, {} );
57
-
58
- export const blocksFixture = toArray( blocksByTemplatesFixture );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/starter-page-templates/page-template-modal/components/test/template-selector-control-test.js DELETED
@@ -1,200 +0,0 @@
1
- /**
2
- * External dependencies
3
- */
4
- /* eslint-disable import/no-extraneous-dependencies */
5
- import { uniqueId, omit } from 'lodash';
6
- /* eslint-enable import/no-extraneous-dependencies */
7
-
8
- import { render, fireEvent } from '@testing-library/react';
9
-
10
- import { templatesFixture, blocksByTemplatesFixture } from './helpers/templates-blocks-helpers';
11
- import { TemplateSelectorControl } from '../template-selector-control';
12
-
13
- // Mock out this component until @wordpress/block-editor
14
- // `BlockPreview` component is available as default export.
15
- // Once available, swap this mock to mocking out `BlockPreview`
16
- // directly as it causes too many knock on effects when rendering
17
- jest.mock( '../block-template-preview', () => () => {
18
- return <div data-testid="block-template-preview">MockedBlockPreview</div>;
19
- } );
20
-
21
- // Required to handle `BlockPreview` usage of Mutation Observer
22
- beforeAll(
23
- ( global.MutationObserver = jest.fn( () => {
24
- return {
25
- observe: jest.fn(),
26
- disconnect: jest.fn(),
27
- };
28
- } ) )
29
- );
30
-
31
- afterAll( () => {
32
- global.MutationObserver.mockRestore();
33
- } );
34
-
35
- const testUniqueId = uniqueId();
36
-
37
- describe( 'TemplateSelectorControl', () => {
38
- const siteInformation = {
39
- title: 'gutenberg-training',
40
- vertical: 'Business',
41
- };
42
-
43
- describe( 'Basic rendering', () => {
44
- it( 'renders with required props', () => {
45
- const { getByText, container } = render(
46
- <TemplateSelectorControl
47
- label="Select a Template..."
48
- instanceId={ testUniqueId }
49
- templates={ templatesFixture }
50
- blocksByTemplates={ blocksByTemplatesFixture }
51
- siteInformation={ siteInformation }
52
- />
53
- );
54
-
55
- expect( getByText( 'Select a Template...' ) ).toBeInTheDocument();
56
- expect( getByText( 'Blank' ) ).toBeInTheDocument();
57
- expect( document.querySelectorAll( 'button.template-selector-item__label' ) ).toHaveLength(
58
- 4
59
- );
60
- expect( document.querySelectorAll( 'button.is-selected' ) ).toHaveLength( 0 );
61
- expect( container ).toMatchSnapshot();
62
- } );
63
-
64
- it( 'highlights the selected template', () => {
65
- render(
66
- <TemplateSelectorControl
67
- label="Select a Template..."
68
- instanceId={ testUniqueId }
69
- templates={ templatesFixture }
70
- blocksByTemplates={ blocksByTemplatesFixture }
71
- siteInformation={ siteInformation }
72
- selectedTemplate={ templatesFixture[ 0 ].slug }
73
- />
74
- );
75
-
76
- expect( document.querySelectorAll( 'button.is-selected' ) ).toHaveLength( 1 );
77
- } );
78
-
79
- it( 'does not render when missing templates prop', () => {
80
- const { queryByText, queryByTestId } = render(
81
- <TemplateSelectorControl
82
- label="Select a Template..."
83
- instanceId={ testUniqueId }
84
- blocksByTemplates={ blocksByTemplatesFixture }
85
- />
86
- );
87
-
88
- // use `queryBy` to avoid throwing an error with `getBy`
89
- expect( queryByText( 'Select a Template...' ) ).not.toBeInTheDocument();
90
- expect( queryByTestId( 'template-selector-control-options' ) ).not.toBeInTheDocument();
91
- } );
92
-
93
- it( 'does not render when templates prop is not an Array', () => {
94
- const { queryByText, queryByTestId } = render(
95
- <TemplateSelectorControl
96
- label="Select a Template..."
97
- instanceId={ testUniqueId }
98
- templates={ 'evil stuff here' }
99
- blocksByTemplates={ blocksByTemplatesFixture }
100
- />
101
- );
102
-
103
- expect( queryByText( 'Select a Template...' ) ).not.toBeInTheDocument();
104
- expect( queryByTestId( 'template-selector-control-options' ) ).not.toBeInTheDocument();
105
- } );
106
- } );
107
-
108
- describe( 'Event handlers', () => {
109
- it( 'calls onTemplateSelect prop when template is clicked', () => {
110
- const onSelectSpy = jest.fn();
111
-
112
- const { getByText } = render(
113
- <TemplateSelectorControl
114
- label="Select a Template..."
115
- instanceId={ testUniqueId }
116
- templates={ templatesFixture }
117
- blocksByTemplates={ blocksByTemplatesFixture }
118
- siteInformation={ siteInformation }
119
- onTemplateSelect={ onSelectSpy }
120
- />
121
- );
122
-
123
- fireEvent.click( getByText( 'Template 3' ) );
124
-
125
- expect( onSelectSpy ).toHaveBeenCalled();
126
- } );
127
- } );
128
-
129
- describe( 'Static previews', () => {
130
- it( 'renders in static preview mode by default ', () => {
131
- const { getByAltText } = render(
132
- <TemplateSelectorControl
133
- label="Select a Template..."
134
- instanceId={ testUniqueId }
135
- templates={ templatesFixture }
136
- blocksByTemplates={ blocksByTemplatesFixture }
137
- siteInformation={ siteInformation }
138
- />
139
- );
140
-
141
- expect( getByAltText( 'Testing alt 2' ) ).toBeInTheDocument();
142
- expect( document.querySelectorAll( 'img.template-selector-item__media' ) ).toHaveLength( 4 );
143
- } );
144
-
145
- it( 'renders in "blank" mode when static preview is not provided ', () => {
146
- const templatesFixtureWithoutPreviews = templatesFixture.map( template =>
147
- omit( template, 'preview' )
148
- );
149
-
150
- const { getByText } = render(
151
- <TemplateSelectorControl
152
- label="Select a Template..."
153
- instanceId={ testUniqueId }
154
- templates={ templatesFixtureWithoutPreviews }
155
- blocksByTemplates={ blocksByTemplatesFixture }
156
- siteInformation={ siteInformation }
157
- />
158
- );
159
-
160
- expect( getByText( 'Select a Template...' ) ).toBeInTheDocument();
161
- expect( getByText( 'Blank' ) ).toBeInTheDocument();
162
- } );
163
- } );
164
-
165
- describe( 'Dynamic previews', () => {
166
- it( 'renders in dynamic preview mode when useDynamicPreview is true', () => {
167
- const { queryByAltText, getAllByTestId } = render(
168
- <TemplateSelectorControl
169
- label="Select a Template..."
170
- instanceId={ testUniqueId }
171
- templates={ templatesFixture }
172
- blocksByTemplates={ blocksByTemplatesFixture }
173
- siteInformation={ siteInformation }
174
- useDynamicPreview={ true }
175
- />
176
- );
177
-
178
- const mockedBlockTemplatePreviews = getAllByTestId( 'block-template-preview' );
179
-
180
- expect( mockedBlockTemplatePreviews ).toHaveLength( 4 );
181
- expect( queryByAltText( 'Testing alt 2' ) ).not.toBeInTheDocument();
182
- expect( document.querySelectorAll( 'img.template-selector-item__media' ) ).toHaveLength( 0 );
183
- } );
184
-
185
- it( 'does not render without blocksByTemplatesFixture prop when in dynamic mode', () => {
186
- const { queryByLabelText, queryByTestId } = render(
187
- <TemplateSelectorControl
188
- label="Select a Template..."
189
- instanceId={ testUniqueId }
190
- templates={ templatesFixture }
191
- siteInformation={ siteInformation }
192
- useDynamicPreview={ true }
193
- />
194
- );
195
-
196
- expect( queryByLabelText( 'Select a Template...' ) ).not.toBeInTheDocument();
197
- expect( queryByTestId( 'template-selector-control-options' ) ).not.toBeInTheDocument();
198
- } );
199
- } );
200
- } );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/starter-page-templates/page-template-modal/components/test/template-selector-preview-test.js DELETED
@@ -1,65 +0,0 @@
1
- /**
2
- * External dependencies
3
- */
4
- import { render } from '@testing-library/react';
5
- import { blocksFixture } from './helpers/templates-blocks-helpers';
6
- import TemplateSelectorPreview from '../template-selector-preview';
7
-
8
- // Mock the "pass through" version of the `BlockPreview` component
9
- // See `components/block-preview.js`
10
- jest.mock( '../block-preview', () => () => {
11
- return <div data-testid="block-template-preview">MockedBlockPreview</div>;
12
- } );
13
-
14
- // Required to handle `BlockPreview` usage of Mutation Observer
15
- beforeAll(
16
- ( global.MutationObserver = jest.fn( () => {
17
- return {
18
- observe: jest.fn(),
19
- disconnect: jest.fn(),
20
- };
21
- } ) )
22
- );
23
-
24
- afterAll( () => {
25
- global.MutationObserver.mockRestore();
26
- } );
27
-
28
- describe( 'TemplateSelectorPreview', () => {
29
- describe( 'Basic rendering', () => {
30
- it( 'renders the preview when blocks are provided', () => {
31
- const { queryByTestId, container } = render(
32
- <TemplateSelectorPreview blocks={ blocksFixture } viewportWidth={ 960 } />
33
- );
34
-
35
- expect( queryByTestId( 'block-template-preview' ) ).toBeInTheDocument();
36
- expect( container ).toMatchSnapshot();
37
- } );
38
-
39
- it( 'renders placeholder when no blocks are provided', () => {
40
- const { getByText, queryByTestId } = render(
41
- <TemplateSelectorPreview viewportWidth={ 960 } />
42
- );
43
-
44
- expect( getByText( 'Select a layout to preview.' ) ).toBeInTheDocument();
45
- expect( queryByTestId( 'block-template-preview' ) ).not.toBeInTheDocument();
46
- } );
47
-
48
- it( 'renders placeholder when blocks is not an array', () => {
49
- const invalidBlocksProp = {
50
- 'some-block-1': {
51
- block: 'foo',
52
- },
53
- 'some-block-2': {
54
- block: 'bar',
55
- },
56
- };
57
- const { getByText, queryByTestId } = render(
58
- <TemplateSelectorPreview blocks={ invalidBlocksProp } viewportWidth={ 960 } />
59
- );
60
-
61
- expect( getByText( 'Select a layout to preview.' ) ).toBeInTheDocument();
62
- expect( queryByTestId( 'block-template-preview' ) ).not.toBeInTheDocument();
63
- } );
64
- } );
65
- } );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/starter-page-templates/page-template-modal/index.js DELETED
@@ -1,401 +0,0 @@
1
- /* eslint-disable import/no-extraneous-dependencies */
2
- /**
3
- * External dependencies
4
- */
5
- import {
6
- find,
7
- isEmpty,
8
- reduce,
9
- get,
10
- keyBy,
11
- mapValues,
12
- memoize,
13
- partition,
14
- reject,
15
- sortBy,
16
- } from 'lodash';
17
- import classnames from 'classnames';
18
- import '@wordpress/nux';
19
- import { __, sprintf } from '@wordpress/i18n';
20
- import { compose } from '@wordpress/compose';
21
- import { Button, Modal, Spinner, IconButton } from '@wordpress/components';
22
- import { withDispatch, withSelect } from '@wordpress/data';
23
- import { Component } from '@wordpress/element';
24
- import { parse as parseBlocks } from '@wordpress/blocks';
25
-
26
- /**
27
- * Internal dependencies
28
- */
29
- import './styles/starter-page-templates-editor.scss';
30
- import TemplateSelectorControl from './components/template-selector-control';
31
- import TemplateSelectorPreview from './components/template-selector-preview';
32
- import { trackDismiss, trackSelection, trackView } from './utils/tracking';
33
- import replacePlaceholders from './utils/replace-placeholders';
34
- import ensureAssets from './utils/ensure-assets';
35
- /* eslint-enable import/no-extraneous-dependencies */
36
-
37
- const DEFAULT_HOMEPAGE_TEMPLATE = 'maywood';
38
-
39
- class PageTemplateModal extends Component {
40
- state = {
41
- isLoading: false,
42
- previewedTemplate: null,
43
- error: null,
44
- isOpen: false,
45
- };
46
-
47
- // Extract titles for faster lookup.
48
- getTitlesByTemplateSlugs = memoize( templates =>
49
- mapValues( keyBy( templates, 'slug' ), 'title' )
50
- );
51
-
52
- // Parse templates blocks and memoize them.
53
- getBlocksByTemplateSlugs = memoize( templates =>
54
- reduce(
55
- templates,
56
- ( prev, { slug, content } ) => {
57
- prev[ slug ] = content
58
- ? parseBlocks( replacePlaceholders( content, this.props.siteInformation ) )
59
- : [];
60
- return prev;
61
- },
62
- {}
63
- )
64
- );
65
-
66
- static getDerivedStateFromProps( props, state ) {
67
- // The only time `state.previewedTemplate` isn't set is before `templates`
68
- // are loaded. As soon as we have our `templates`, we set it using
69
- // `this.getDefaultSelectedTemplate`. Afterwards, the user can select a
70
- // different template, but can never un-select it.
71
- // This makes it a reliable indicator for whether the modal has just been launched.
72
- // It's also possible that `templates` are present during initial mount, in which
73
- // case this will be called before `componentDidMount`, which is also fine.
74
- if ( ! state.previewedTemplate && ! isEmpty( props.templates ) ) {
75
- // Show the modal, and select the first template automatically.
76
- return {
77
- isOpen: true,
78
- previewedTemplate: PageTemplateModal.getDefaultSelectedTemplate( props ),
79
- };
80
- }
81
- return null;
82
- }
83
-
84
- componentDidMount() {
85
- if ( this.state.isOpen ) {
86
- trackView( this.props.segment.id, this.props.vertical.id );
87
- }
88
- }
89
-
90
- componentDidUpdate( prevProps, prevState ) {
91
- // Only track when the modal is first displayed
92
- // and if it didn't already happen during componentDidMount.
93
- if ( ! prevState.isOpen && this.state.isOpen ) {
94
- trackView( this.props.segment.id, this.props.vertical.id );
95
- }
96
- }
97
-
98
- static getDefaultSelectedTemplate = props => {
99
- const blankTemplate = get( props.templates, [ 0, 'slug' ] );
100
- let previouslyChosenTemplate = props._starter_page_template;
101
-
102
- // Usally the "new page" case.
103
- if ( ! props.isFrontPage && ! previouslyChosenTemplate ) {
104
- return blankTemplate;
105
- }
106
-
107
- // Normalize "home" slug into the current theme.
108
- if ( previouslyChosenTemplate === 'home' ) {
109
- previouslyChosenTemplate = props.theme;
110
- }
111
-
112
- const slug = previouslyChosenTemplate || props.theme;
113
-
114
- if ( find( props.templates, { slug } ) ) {
115
- return slug;
116
- } else if ( find( props.templates, { slug: DEFAULT_HOMEPAGE_TEMPLATE } ) ) {
117
- return DEFAULT_HOMEPAGE_TEMPLATE;
118
- }
119
- return blankTemplate;
120
- };
121
-
122
- setTemplate = slug => {
123
- // Track selection and mark post as using a template in its postmeta.
124
- trackSelection( this.props.segment.id, this.props.vertical.id, slug );
125
- this.props.saveTemplateChoice( slug );
126
-
127
- const isHomepageTemplate = find( this.props.templates, { slug, category: 'home' } );
128
-
129
- // Load content.
130
- const blocks = this.getBlocksByTemplateSlug( slug );
131
- // Only overwrite the page title if the template is not one of the Homepage Layouts
132
- const title = isHomepageTemplate ? null : this.getTitleByTemplateSlug( slug );
133
-
134
- // Skip inserting if there's nothing to insert.
135
- if ( ! blocks || ! blocks.length ) {
136
- this.setState( { isOpen: false } );
137
- return;
138
- }
139
-
140
- // Show loading state.
141
- this.setState( {
142
- error: null,
143
- isLoading: true,
144
- } );
145
-
146
- // Make sure all blocks use local assets before inserting.
147
- this.maybePrefetchAssets( blocks )
148
- .then( blocksWithAssets => {
149
- // Don't insert anything if the user clicked Cancel/Close
150
- // before we loaded everything.
151
- if ( ! this.state.isOpen ) {
152
- return;
153
- }
154
-
155
- this.props.insertTemplate( title, blocksWithAssets );
156
- this.setState( { isOpen: false } );
157
- } )
158
- .catch( error => {
159
- this.setState( {
160
- isLoading: false,
161
- error,
162
- } );
163
- } );
164
- };
165
-
166
- maybePrefetchAssets = blocks => {
167
- return this.props.shouldPrefetchAssets ? ensureAssets( blocks ) : Promise.resolve( blocks );
168
- };
169
-
170
- handleConfirmation = slug => {
171
- if ( typeof slug !== 'string' ) {
172
- slug = this.state.previewedTemplate;
173
- }
174
-
175
- this.setTemplate( slug );
176
-
177
- // Turn off sidebar's instance of modal
178
- if ( this.props.isPromptedFromSidebar ) {
179
- this.props.toggleTemplateModal();
180
- }
181
- };
182
-
183
- previewTemplate = slug => {
184
- this.setState( { previewedTemplate: slug } );
185
-
186
- /**
187
- * Determines (based on whether the large preview is able to be visible at the
188
- * current breakpoint) whether or not the Template selection UI interaction model
189
- * should be select _and_ confirm or simply a single "tap to confirm".
190
- */
191
- const largeTplPreviewVisible = window.matchMedia( '(min-width: 660px)' ).matches;
192
- // Confirm the template when large preview isn't visible
193
- if ( ! largeTplPreviewVisible ) {
194
- this.handleConfirmation( slug );
195
- }
196
- };
197
-
198
- closeModal = event => {
199
- // Check to see if the Blur event occurred on the buttons inside of the Modal.
200
- // If it did then we don't want to dismiss the Modal for this type of Blur.
201
- if ( event.target.matches( 'button.template-selector-item__label' ) ) {
202
- return false;
203
- }
204
-
205
- trackDismiss( this.props.segment.id, this.props.vertical.id );
206
-
207
- // Try if we have specific URL to go back to, otherwise go to the page list.
208
- const calypsoifyCloseUrl = get( window, [ 'calypsoifyGutenberg', 'closeUrl' ] );
209
- window.top.location = calypsoifyCloseUrl || 'edit.php?post_type=page';
210
- };
211
-
212
- getBlocksByTemplateSlug( slug ) {
213
- return get( this.getBlocksByTemplateSlugs( this.props.templates ), [ slug ], [] );
214
- }
215
-
216
- getTitleByTemplateSlug( slug ) {
217
- return get( this.getTitlesByTemplateSlugs( this.props.templates ), [ slug ], '' );
218
- }
219
-
220
- getTemplateGroups = () => {
221
- const [ homepageTemplates, defaultTemplates ] = partition( this.props.templates, {
222
- category: 'home',
223
- } );
224
-
225
- const currentThemeTemplate =
226
- find( this.props.templates, { slug: this.props.theme } ) ||
227
- find( this.props.templates, { slug: DEFAULT_HOMEPAGE_TEMPLATE } );
228
-
229
- if ( ! this.props.isFrontPage || ! currentThemeTemplate ) {
230
- return { homepageTemplates: sortBy( homepageTemplates, 'title' ), defaultTemplates };
231
- }
232
-
233
- const otherHomepageTemplates = reject( homepageTemplates, { slug: currentThemeTemplate.slug } );
234
-
235
- const sortedHomepageTemplates = [
236
- currentThemeTemplate,
237
- ...sortBy( otherHomepageTemplates, 'title' ),
238
- ];
239
-
240
- return { homepageTemplates: sortedHomepageTemplates, defaultTemplates };
241
- };
242
-
243
- renderTemplatesList = ( templatesList, legendLabel ) => (
244
- <fieldset className="page-template-modal__list">
245
- <legend className="page-template-modal__form-title">{ legendLabel }</legend>
246
- <TemplateSelectorControl
247
- label={ __( 'Layout', 'full-site-editing' ) }
248
- templates={ templatesList }
249
- blocksByTemplates={ this.getBlocksByTemplateSlugs( this.props.templates ) }
250
- onTemplateSelect={ this.previewTemplate }
251
- useDynamicPreview={ false }
252
- siteInformation={ this.props.siteInformation }
253
- selectedTemplate={ this.state.previewedTemplate }
254
- />
255
- </fieldset>
256
- );
257
-
258
- render() {
259
- const { previewedTemplate, isOpen, isLoading } = this.state;
260
- const { isPromptedFromSidebar } = this.props;
261
-
262
- if ( ! isOpen ) {
263
- return null;
264
- }
265
-
266
- const { homepageTemplates, defaultTemplates } = this.getTemplateGroups();
267
-
268
- return (
269
- <Modal
270
- title={ __( 'Select Page Layout', 'full-site-editing' ) }
271
- className="page-template-modal"
272
- overlayClassName="page-template-modal-screen-overlay"
273
- shouldCloseOnClickOutside={ false }
274
- // Using both variants here to be compatible with new Gutenberg and old (older than 6.6).
275
- isDismissable={ false }
276
- isDismissible={ false }
277
- >
278
- { isPromptedFromSidebar ? (
279
- <IconButton
280
- className="page-template-modal__close-button components-icon-button"
281
- onClick={ this.props.toggleTemplateModal }
282
- icon="no-alt"
283
- label={ __( 'Close Layout Selector' ) }
284
- />
285
- ) : (
286
- <IconButton
287
- className="page-template-modal__close-button components-icon-button"
288
- onClick={ this.closeModal }
289
- icon="arrow-left-alt2"
290
- label={ __( 'Go back' ) }
291
- />
292
- ) }
293
-
294
- <div className="page-template-modal__inner">
295
- { isLoading ? (
296
- <div className="page-template-modal__loading">
297
- <Spinner />
298
- { __( 'Adding layout…', 'full-site-editing' ) }
299
- </div>
300
- ) : (
301
- <>
302
- <form className="page-template-modal__form">
303
- { this.props.isFrontPage ? (
304
- <>
305
- { this.renderTemplatesList(
306
- homepageTemplates,
307
- __( 'Recommended Layouts', 'full-site-editing' )
308
- ) }
309
- { this.renderTemplatesList(
310
- defaultTemplates,
311
- __( 'Other Page Layouts', 'full-site-editing' )
312
- ) }
313
- </>
314
- ) : (
315
- <>
316
- { this.renderTemplatesList(
317
- defaultTemplates,
318
- __( 'Recommended Layouts', 'full-site-editing' )
319
- ) }
320
- { this.renderTemplatesList(
321
- homepageTemplates,
322
- __( 'Homepage Layouts', 'full-site-editing' )
323
- ) }
324
- </>
325
- ) }
326
- </form>
327
- <TemplateSelectorPreview
328
- blocks={ this.getBlocksByTemplateSlug( previewedTemplate ) }
329
- viewportWidth={ 960 }
330
- title={ this.getTitleByTemplateSlug( previewedTemplate ) }
331
- />
332
- </>
333
- ) }
334
- </div>
335
- <div
336
- className={ classnames( 'page-template-modal__buttons', {
337
- 'is-visually-hidden': isEmpty( previewedTemplate ) || isLoading,
338
- } ) }
339
- >
340
- <Button
341
- isPrimary
342
- isLarge
343
- disabled={ isEmpty( previewedTemplate ) || isLoading }
344
- onClick={ this.handleConfirmation }
345
- >
346
- { sprintf(
347
- __( 'Use %s layout', 'full-site-editing' ),
348
- this.getTitleByTemplateSlug( previewedTemplate )
349
- ) }
350
- </Button>
351
- </div>
352
- </Modal>
353
- );
354
- }
355
- }
356
-
357
- export const PageTemplatesPlugin = compose(
358
- withSelect( select => {
359
- const getMeta = () => select( 'core/editor' ).getEditedPostAttribute( 'meta' );
360
- const { _starter_page_template } = getMeta();
361
- return {
362
- getMeta,
363
- _starter_page_template,
364
- postContentBlock: select( 'core/editor' )
365
- .getBlocks()
366
- .find( block => block.name === 'a8c/post-content' ),
367
- };
368
- } ),
369
- withDispatch( ( dispatch, ownProps ) => {
370
- // Disable tips right away as the collide with the modal window.
371
- dispatch( 'core/nux' ).disableTips();
372
-
373
- const editorDispatcher = dispatch( 'core/editor' );
374
- return {
375
- saveTemplateChoice: slug => {
376
- // Save selected template slug in meta.
377
- const currentMeta = ownProps.getMeta();
378
- editorDispatcher.editPost( {
379
- meta: {
380
- ...currentMeta,
381
- _starter_page_template: slug,
382
- },
383
- } );
384
- },
385
- insertTemplate: ( title, blocks ) => {
386
- // Set post title.
387
- if ( title ) {
388
- editorDispatcher.editPost( { title } );
389
- }
390
-
391
- // Replace blocks.
392
- const postContentBlock = ownProps.postContentBlock;
393
- dispatch( 'core/block-editor' ).replaceInnerBlocks(
394
- postContentBlock ? postContentBlock.clientId : '',
395
- blocks,
396
- false
397
- );
398
- },
399
- };
400
- } )
401
- )( PageTemplateModal );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/starter-page-templates/page-template-modal/styles/starter-page-templates-editor.scss DELETED
@@ -1,503 +0,0 @@
1
- @mixin screen-reader-text() {
2
- border: 0;
3
- clip: rect( 1px, 1px, 1px, 1px );
4
- clip-path: inset( 50% );
5
- height: 1px;
6
- margin: -1px;
7
- overflow: hidden;
8
- padding: 0;
9
- position: absolute;
10
- width: 1px;
11
- word-wrap: normal !important;
12
- }
13
-
14
- $template-modal-background-color: #eeeeee;
15
- $template-selector-border-color: #e2e4e7;
16
- $template-selector-border-color-selected: #555d66;
17
- $template-selector-border-color-active: #00a0d2;
18
- $template-selector-border-color-hover: #c9c9ca;
19
- $template-selector-empty-background: #fff;
20
- $template-selector-modal-offset-bottom: 25px;
21
- $template-selector-modal-offset-right: 32px;
22
- $template-selector-blank-template-mobile-height: 70px;
23
- $template-large-preview-title-height: 120px;
24
-
25
- // Preview positioning
26
- $preview-right-margin: 24px;
27
-
28
- // Breakpoints
29
- $breakpoint-mobile: 660px;
30
- $breakpoint-tablet: 783px;
31
- $breakpoint-desktop: 961px;
32
- $breakpoint-huge: 1648px;
33
-
34
- // WP.org sidebar and admin bar sizes
35
- $wp-org-sidebar-full: 160px;
36
- $wp-org-sidebar-collapsed: 36px;
37
- $wp-org-admin-bar-full: 32px;
38
- $wp-org-admin-bar-mobile: 46px;
39
-
40
- // Modal Overlay
41
- .page-template-modal-screen-overlay {
42
- animation: none;
43
- background-color: transparent; // hide the overlay visually
44
- z-index: 99; // Right below the wp-admin admin bar and sidebar.
45
- }
46
-
47
- // When not in fullscreen mode allow space for WP.org sidebar
48
- body:not( .is-fullscreen-mode ) {
49
- .page-template-modal-screen-overlay {
50
- @media screen and ( min-width: $breakpoint-tablet ) {
51
- left: $wp-org-sidebar-collapsed;
52
- }
53
-
54
- @media screen and ( min-width: $breakpoint-desktop ) {
55
- left: $wp-org-sidebar-full;
56
- }
57
- }
58
- @media screen and ( min-width: $breakpoint-tablet ) {
59
- &.folded .page-template-modal-screen-overlay {
60
- left: $wp-org-sidebar-collapsed;
61
- }
62
- &:not( .folded ):not( .auto-fold ) .page-template-modal-screen-overlay {
63
- left: $wp-org-sidebar-full;
64
- }
65
- }
66
- }
67
-
68
- // Allow space for admin bar if present and not in full screen mode
69
- body.admin-bar:not( .is-fullscreen-mode ) .page-template-modal-screen-overlay {
70
- top: $wp-org-admin-bar-mobile;
71
-
72
- @media screen and ( min-width: $breakpoint-tablet ) {
73
- top: $wp-org-admin-bar-full;
74
- }
75
- }
76
-
77
- // Full screen modal
78
- .page-template-modal {
79
- width: 100%;
80
- height: 100vh;
81
- animation: none;
82
- box-shadow: none; // cancel "modal" appearance
83
- border: none; // cancel "modal" appearance
84
- top: 0; // overlay the Block Editor toolbar
85
- left: 0;
86
- right: 0;
87
- bottom: 0;
88
- transform: none;
89
- max-width: none;
90
- max-height: none;
91
- background-color: $template-modal-background-color;
92
- }
93
-
94
- .page-template-modal .components-modal__header-heading-container {
95
- @include screen-reader-text();
96
- }
97
-
98
- // Show close button in all modes.
99
- .page-template-modal__close-button {
100
- display: block;
101
- position: absolute;
102
- z-index: 20;
103
- top: 9px;
104
- width: 36px;
105
- height: 36px;
106
- left: 10px;
107
- }
108
-
109
- .page-template-modal .components-modal__header::after {
110
- display: block;
111
- position: absolute;
112
- content: ' ';
113
- border-right: 1px solid $template-selector-border-color;
114
- height: 100%;
115
- left: 56px;
116
- }
117
-
118
- .page-template-modal .components-modal__content {
119
- overflow-y: scroll;
120
- -webkit-overflow-scrolling: touch;
121
- }
122
- .page-template-modal__inner {
123
- position: relative;
124
- margin: 0 auto;
125
- padding: 0 20px 40px;
126
- }
127
-
128
- .page-template-modal__list {
129
- margin-bottom: 20px;
130
-
131
- .components-base-control__label {
132
- @include screen-reader-text();
133
- }
134
- }
135
-
136
- .template-selector-control__options {
137
- display: grid;
138
- // stylelint-disable-next-line unit-whitelist
139
- grid-template-columns: 1fr;
140
- grid-gap: 1.75em;
141
-
142
- @media screen and ( min-width: $breakpoint-mobile ) {
143
- margin-top: 0;
144
- // stylelint-disable unit-whitelist
145
- grid-template-columns: repeat(
146
- auto-fit,
147
- minmax( 110px, 1fr )
148
- ); // allow grid to take over number of cols on large screens
149
- // stylelint-enable unit-whitelist
150
- }
151
- }
152
-
153
- .template-selector-item__label {
154
- display: block;
155
- width: 100%;
156
- font-size: 14px;
157
- text-align: center;
158
- border: solid 2px $template-selector-border-color;
159
- border-radius: 6px;
160
- cursor: pointer;
161
- appearance: none;
162
- padding: 0;
163
- overflow: hidden;
164
- background-color: $template-selector-empty-background;
165
- position: relative;
166
- transform: translateZ( 0 ); // Fix for Safari rounded border overflow (1/2).
167
-
168
- .template-selector-item__template-title {
169
- width: 100%;
170
- position: absolute;
171
- bottom: 0;
172
- left: 0;
173
- height: 40px;
174
- line-height: 40px;
175
- background-color: $template-selector-empty-background;
176
- }
177
-
178
- &:focus {
179
- box-shadow: 0 0 0 1px $template-selector-empty-background,
180
- 0 0 0 3px $template-selector-border-color-active;
181
- // Windows High Contrast mode will show this outline, but not the box-shadow.
182
- outline: 2px solid transparent;
183
- }
184
-
185
- &:hover {
186
- border: solid 2px $template-selector-border-color-hover;
187
- }
188
-
189
- &.is-selected {
190
- border: solid 2px $template-selector-border-color-selected;
191
- // Windows High Contrast mode will show this outline, but not the box-shadow.
192
- outline: 2px solid transparent;
193
- outline-offset: -2px;
194
-
195
- &:focus {
196
- box-shadow: 0 0 0 1px $template-selector-empty-background,
197
- 0 0 0 3px $template-selector-border-color-active;
198
- border: solid 2px $template-selector-border-color-selected;
199
-
200
- // Windows High Contrast mode will show this outline, but not the box-shadow.
201
- outline: 4px solid transparent;
202
- outline-offset: -4px;
203
- }
204
- }
205
- }
206
-
207
- .template-selector-item__preview-wrap {
208
- width: 100%;
209
- display: block;
210
- margin: 0 auto;
211
- background: $template-selector-empty-background;
212
- border-radius: 0;
213
- overflow: hidden;
214
- height: 0;
215
- padding-top: 120%;
216
- box-sizing: content-box;
217
- position: relative;
218
- pointer-events: none;
219
- opacity: 1;
220
- transform: translateZ( 0 ); // Fix for Safari rounded border overflow (2/2).
221
-
222
- @media screen and ( min-width: $breakpoint-mobile ) {
223
- padding-top: 100%; // Aspect radio boxes. It will take the 100% of width.
224
- }
225
-
226
- &.is-rendering {
227
- opacity: 0.5;
228
- }
229
-
230
- .block-editor-block-list__layout,
231
- .block-editor-block-list__block {
232
- padding: inherit;
233
- }
234
- }
235
-
236
- .template-selector-item__media {
237
- width: 100%;
238
- display: block;
239
- position: absolute;
240
- top: 0;
241
- left: 0;
242
- }
243
-
244
- // Blank template
245
- @media screen and ( max-width: ( $breakpoint-mobile - 1px ) ) {
246
- .template-selector-control__template:first-child {
247
- .template-selector-item__preview-wrap {
248
- padding-top: 0%;
249
- height: $template-selector-blank-template-mobile-height;
250
- }
251
- .template-selector-item__template-title {
252
- height: $template-selector-blank-template-mobile-height;
253
- line-height: $template-selector-blank-template-mobile-height;
254
- }
255
- }
256
- }
257
-
258
- .page-template-modal__form {
259
- @media screen and ( min-width: $breakpoint-mobile ) {
260
- max-width: 20%;
261
- }
262
-
263
- @media screen and ( min-width: $breakpoint-tablet ) {
264
- max-width: 30%;
265
- }
266
- }
267
-
268
- .page-template-modal__form-title {
269
- font-weight: bold;
270
- margin-bottom: 1em;
271
- text-align: center;
272
- @media screen and ( min-width: $breakpoint-mobile ) {
273
- text-align: left;
274
- }
275
- }
276
-
277
- .page-template-modal__buttons {
278
- position: absolute;
279
- right: 0;
280
- top: 0;
281
- z-index: 10;
282
- height: 56px;
283
- display: flex;
284
- align-items: center;
285
- padding-right: 24px;
286
-
287
- @media screen and ( min-width: $breakpoint-mobile ) {
288
- display: flex;
289
- }
290
-
291
- &.is-visually-hidden {
292
- @include screen-reader-text();
293
- }
294
-
295
- .components-button {
296
- height: 33px; // match to Gutenberg toolbar styles
297
- line-height: 32px; // match to Gutenberg toolbar styles
298
- }
299
- }
300
-
301
- // Template Selector Preview
302
- .template-selector-preview {
303
- display: none;
304
- position: fixed;
305
- top: 111px + $wp-org-admin-bar-mobile;
306
- bottom: 24px;
307
- left: calc( 20% + #{$preview-right-margin * 2} );
308
- right: $preview-right-margin;
309
- background: $template-selector-empty-background;
310
- border-radius: 2px;
311
- overflow-x: hidden;
312
- overflow-y: auto;
313
- box-shadow: 0 2px 2px 0 rgba( 0, 0, 0, 0.14 ), 0 3px 1px -2px rgba( 0, 0, 0, 0.12 ),
314
- 0 1px 5px 0 rgba( 0, 0, 0, 0.2 );
315
-
316
- @media screen and ( min-width: $breakpoint-mobile ) {
317
- display: block;
318
- &.is-blank-preview {
319
- align-items: center;
320
- display: flex;
321
- justify-content: center;
322
- }
323
- }
324
-
325
- @media screen and ( min-width: $breakpoint-tablet ) {
326
- top: 111px + $wp-org-admin-bar-full;
327
- left: calc( 30% + #{$preview-right-margin * 1.5 + $wp-org-sidebar-collapsed} );
328
- body:not( .auto-fold ):not( .folded ) & {
329
- left: calc( 30% + #{$preview-right-margin / 2 + $wp-org-sidebar-full} );
330
- }
331
- }
332
- @media screen and ( min-width: $breakpoint-desktop ) {
333
- left: calc( 30% + #{$preview-right-margin / 2 + $wp-org-sidebar-full} );
334
- body.folded & {
335
- left: calc( 30% + #{$preview-right-margin * 1.5 + $wp-org-sidebar-collapsed} );
336
- }
337
- }
338
-
339
- body.is-fullscreen-mode & {
340
- top: 111px;
341
- @media screen and ( min-width: $breakpoint-tablet ) {
342
- left: calc( 30% + #{$preview-right-margin * 2} ) !important;
343
- }
344
- }
345
-
346
- .edit-post-visual-editor {
347
- margin: 0;
348
- padding: 0;
349
- }
350
-
351
- .editor-styles-wrapper {
352
- .template-selector-preview__offset-correction {
353
- position: relative;
354
- top: $template-large-preview-title-height;
355
- }
356
-
357
- .editor-post-title {
358
- transform-origin: top center;
359
- width: 100%;
360
- display: block;
361
- position: absolute;
362
- top: 0;
363
- }
364
-
365
- .editor-post-title,
366
- .editor-post-title__block,
367
- .editor-post-title__input {
368
- padding-top: 0;
369
- padding-bottom: 0;
370
- margin-top: 0;
371
- margin-bottom: 0;
372
- .editor-post-title__input {
373
- margin: 0;
374
- padding: 0;
375
- height: $template-large-preview-title-height;
376
- line-height: $template-large-preview-title-height;
377
- overflow: hidden;
378
- resize: none;
379
- }
380
- }
381
- }
382
- }
383
-
384
- .template-selector-preview__placeholder {
385
- color: var( --color-text-subtle );
386
- font-size: 15px;
387
- font-weight: 400;
388
- }
389
-
390
- // Preview adjustments.
391
- // Tweak styles which are inside of the preview container.
392
- .block-editor-block-preview__container {
393
- .editor-styles-wrapper {
394
- .wp-block {
395
- width: 100%;
396
- }
397
-
398
- // `core/cover`
399
- .wp-block[data-type='core/cover'][data-align='full'] {
400
- margin: 0;
401
- .wp-block-cover {
402
- padding: 0;
403
- }
404
- }
405
-
406
- // `core/columns`
407
- /* stylelint-disable selector-combinator-space-before */
408
- .wp-block-columns
409
- > .editor-inner-blocks
410
- > .editor-block-list__layout
411
- > [data-type='core/column']
412
- > .editor-block-list__block-edit
413
- > div
414
- > .block-core-columns
415
- > .editor-inner-blocks {
416
- /* stylelint-enable */
417
- margin-top: 0;
418
- margin-bottom: 0;
419
- }
420
-
421
- .block-editor-block-list__block {
422
- &[data-align='full'] {
423
- margin: 0;
424
- }
425
-
426
- .block-editor-block-list__block-edit {
427
- @media screen and ( min-width: 600px ) {
428
- margin: 0;
429
- }
430
- }
431
- }
432
-
433
- // Fix upstream: https://github.com/WordPress/gutenberg/pull/17202.
434
- .block-editor-block-list__layout,
435
- .block-editor-block-list__block {
436
- padding: inherit;
437
- }
438
- }
439
- }
440
-
441
- // Set full height to preview container to inherits styles defined for themes.
442
- .template-selector-preview .components-disabled,
443
- .template-selector-preview .edit-post-visual-editor,
444
- .template-selector-item__preview-wrap .components-disabled,
445
- .template-selector-item__preview-wrap .edit-post-visual-editor {
446
- height: 100%;
447
-
448
- .editor-styles-wrapper {
449
- height: 100%;
450
- }
451
- }
452
-
453
- .page-template-modal__loading {
454
- position: absolute;
455
- top: 50%;
456
- left: 50%;
457
- transform: translate( -50%, -50% );
458
- display: flex;
459
- align-items: flex-end;
460
-
461
- .components-spinner {
462
- float: none;
463
- }
464
- }
465
-
466
- // Sidebar modal opener goo.
467
- .sidebar-modal-opener {
468
- display: flex;
469
- flex-direction: column;
470
- align-items: center;
471
- justify-content: center;
472
-
473
- .template-selector-item__label {
474
- max-width: 300px;
475
- }
476
-
477
- .template-selector-item__template-title {
478
- font-size: 1.2rem;
479
- }
480
- }
481
-
482
- .sidebar-modal-opener__button {
483
- margin-top: 20px;
484
- }
485
-
486
- .sidebar-modal-opener__warning-modal {
487
- display: flex;
488
- flex-direction: column;
489
- justify-content: center;
490
- align-items: center;
491
- }
492
-
493
- .sidebar-modal-opener__warning-text {
494
- max-width: 300px;
495
- font-size: 1rem;
496
- line-height: 1.5rem;
497
- }
498
-
499
- .sidebar-modal-opener__warning-options {
500
- display: flex;
501
- justify-content: space-around;
502
- margin-top: 20px;
503
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/starter-page-templates/page-template-modal/utils/ensure-assets.js DELETED
@@ -1,213 +0,0 @@
1
- /**
2
- * External dependencies
3
- */
4
- import { reduce, isEmpty, forEach, set, map } from 'lodash';
5
-
6
- /**
7
- * WordPress dependencies
8
- */
9
- import apiFetch from '@wordpress/api-fetch';
10
- import { removeQueryArgs } from '@wordpress/url';
11
-
12
- /**
13
- * A full asset URL.
14
- * @typedef {String} URL
15
- */
16
-
17
- /**
18
- * Gutenberg Block.
19
- * @typedef {Object} GutenbergBlock
20
- * @property {String} clientId A unique id of the block.
21
- * @property {String} name A block name, like "core/paragraph".
22
- * @property {Array<GutenbergBlock>} innerBlocks Nested blocks.
23
- * @property {Object} attributes An object with attributes, different for each block type.
24
- */
25
-
26
- /**
27
- * Usage object contains an info that certain property is used inside another object.
28
- * @typedef {Object} Usage
29
- * @property {String} prop Name of the property.
30
- * @property {Array<String|Number>} path A path inside an object where prop is, defined as list of keys.
31
- */
32
-
33
- /**
34
- * An asset file that is referenced in blocks.
35
- * @typedef {Object} Asset
36
- * @property {URL} url A full URL of the asset.
37
- * @property {Array<Usage>} usages A list of {@link Usage} objects.
38
- */
39
-
40
- /**
41
- * A collection of {@link Asset} objects, keyed by their URLs.
42
- * @typedef {Object.<String, Asset>} Assets URLs as keys, {@link Asset}.as a values.
43
- */
44
-
45
- /**
46
- * FetchSession describes a set of blocks and their assets.
47
- * @typedef {Object} FetchSession
48
- * @property {Array<GutenbergBlock>} blocks List of Gutenberg blocks.
49
- * @property {Object<String, GutenbergBlock>} blocksByClientId Blocks, keyed by their `clientId`
50
- * @property {Assets} assets A list of assets detected in blocks.
51
- */
52
-
53
- /**
54
- * Extends an {@link Assets} object with a new asset and updates its usages.
55
- *
56
- * @param {Assets} assets Object containing assets.
57
- * @param {URL} url A full URL of the asset.
58
- * @param {Array<Usage>} usages A list of {@link Usage} objects.
59
- * @returns {Assets} assets object with the new {@link Asset} included
60
- */
61
- const addAssetToLoad = ( assets, url, usages ) => {
62
- // Remove resizing query arguments from the URL.
63
- url = removeQueryArgs( url, 'w', 's' );
64
-
65
- // Use an existing asset for the URL or make a new one.
66
- const asset = assets[ url ] || {
67
- url,
68
- usages: [],
69
- };
70
-
71
- // Return new result object, extended with the new/updated asset.
72
- return {
73
- ...assets,
74
- [ url ]: {
75
- ...asset,
76
- // Store where exactly block uses id/url so we can update it later.
77
- usages: [ ...asset.usages, ...usages ],
78
- },
79
- };
80
- };
81
-
82
- /**
83
- * This function is used as a reducer iteratee. It checks if the block
84
- * contains any image and if so, enqueues it to be downloaded later.
85
- *
86
- * @param {FetchSession} session Session object.
87
- * @param {GutenbergBlock} block Gutenberg Block object.
88
- * @returns {FetchSession} Updated session object
89
- */
90
- const findAssetsInBlock = ( session, block ) => {
91
- // Save a reference for the block so we can later easily
92
- // find it without any loops and recursion.
93
- session.blocksByClientId[ block.clientId ] = block;
94
-
95
- // Identify assets in blocks where we expect them.
96
- switch ( block.name ) {
97
- // Both of these blocks use same attribute names for image id and url
98
- // and thus we can share the implementation.
99
- case 'core/cover':
100
- case 'core/image': {
101
- const url = block.attributes.url;
102
- if ( url ) {
103
- session.assets = addAssetToLoad( session.assets, url, [
104
- { prop: 'url', path: [ block.clientId, 'attributes', 'url' ] },
105
- { prop: 'id', path: [ block.clientId, 'attributes', 'id' ] },
106
- ] );
107
- }
108
- }
109
- case 'core/media-text': {
110
- const url = block.attributes.mediaUrl;
111
- if ( url && block.attributes.mediaType === 'image' ) {
112
- session.assets = addAssetToLoad( session.assets, url, [
113
- { prop: 'url', path: [ block.clientId, 'attributes', 'mediaUrl' ] },
114
- { prop: 'id', path: [ block.clientId, 'attributes', 'mediaId' ] },
115
- ] );
116
- }
117
- }
118
- case 'core/gallery': {
119
- forEach( block.attributes.images, ( image, i ) => {
120
- session.assets = addAssetToLoad( session.assets, image.url, [
121
- { prop: 'url', path: [ block.clientId, 'attributes', 'images', i, 'url' ] },
122
- { prop: 'url', path: [ block.clientId, 'attributes', 'images', i, 'link' ] },
123
- { prop: 'id', path: [ block.clientId, 'attributes', 'images', i, 'id' ] },
124
- { prop: 'id', path: [ block.clientId, 'attributes', 'ids', i ] },
125
- ] );
126
- } );
127
- }
128
- }
129
-
130
- // Recursively process all inner blocks.
131
- if ( ! isEmpty( block.innerBlocks ) ) {
132
- return reduce( block.innerBlocks, findAssetsInBlock, session );
133
- }
134
-
135
- return session;
136
- };
137
-
138
- /**
139
- * Calls an API that fetches assets and saves the result into the DetectedAssets object.
140
- *
141
- * @param {Assets} assets Assets that were detected from blocks.
142
- * @returns {Promise} Promise that resoves into an object with URLs as keys and fetch results as values.
143
- */
144
- const fetchAssets = async assets => {
145
- return await apiFetch( {
146
- method: 'POST',
147
- path: '/fse/v1/sideload/image/batch',
148
- data: { resources: map( assets ) },
149
- } ).then( response =>
150
- reduce(
151
- assets,
152
- ( fetched, asset ) => {
153
- const { id, source_url } = response.shift();
154
- return {
155
- ...fetched,
156
- [ asset.url ]: { id, url: source_url },
157
- };
158
- },
159
- {}
160
- )
161
- );
162
- };
163
-
164
- /**
165
- * Takes fetched assets and makes sure all their usages will be changed into
166
- * their new local copies.
167
- *
168
- * @param {FetchSession} session A current session.
169
- * @param {Object<String,Object>} fetchedAssets Fetched assets.
170
- * @returns {Array<GutenbergBlock>} A promise resolving into an array of blocks.
171
- */
172
- const getBlocksWithAppliedAssets = ( session, fetchedAssets ) => {
173
- forEach( session.assets, asset => {
174
- const newAsset = fetchedAssets[ asset.url ];
175
- if ( ! newAsset ) {
176
- return;
177
- }
178
- forEach( asset.usages, usage => {
179
- set( session.blocksByClientId, usage.path, newAsset[ usage.prop ] );
180
- } );
181
- } );
182
-
183
- return session.blocks;
184
- };
185
-
186
- /**
187
- * Analyzes blocks and if they use any external assets, ensures they are
188
- * copied into a local site and are used in blocks instead of the remote ones.
189
- *
190
- * @param {Array<GutenbergBlock>} blocks Blocks, as returned by `wp.block.parse`
191
- * @returns {Promise} A promise that resolves into an array of {@link GutenbergBlock} with updated assets
192
- */
193
- const ensureAssetsInBlocks = async blocks => {
194
- // Create a FetchSession object by reducing blocks.
195
- const session = reduce( blocks, findAssetsInBlock, {
196
- assets: {},
197
- blocksByClientId: {},
198
- blocks,
199
- } );
200
-
201
- // No assets found. Proceed with insertion right away.
202
- if ( isEmpty( session.assets ) ) {
203
- return blocks;
204
- }
205
-
206
- // Ensure assets are available on the site and replace originals
207
- // with local copies before inserting the template.
208
- return fetchAssets( session.assets ).then( fetchedAssets => {
209
- return getBlocksWithAppliedAssets( session, fetchedAssets );
210
- } );
211
- };
212
-
213
- export default ensureAssetsInBlocks;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/starter-page-templates/page-template-modal/utils/replace-placeholders.js DELETED
@@ -1,32 +0,0 @@
1
- /**
2
- * External dependencies
3
- */
4
- import { _x } from '@wordpress/i18n';
5
-
6
- const PLACEHOLDER_DEFAULTS = {
7
- Address: _x( '123 Main St', 'default address', 'full-site-editing' ),
8
- Phone: _x( '555-555-5555', 'default phone number', 'full-site-editing' ),
9
- CompanyName: _x( 'Your Company Name', 'default company name', 'full-site-editing' ),
10
- Vertical: _x( 'Business', 'default vertical name', 'full-site-editing' ),
11
- };
12
-
13
- const KEY_MAP = {
14
- CompanyName: 'title',
15
- Address: 'address',
16
- Phone: 'phone',
17
- Vertical: 'vertical',
18
- };
19
-
20
- const replacePlaceholders = ( pageContent, siteInformation = {} ) => {
21
- if ( ! pageContent ) {
22
- return '';
23
- }
24
-
25
- return pageContent.replace( /{{(\w+)}}/g, ( match, placeholder ) => {
26
- const defaultValue = PLACEHOLDER_DEFAULTS[ placeholder ];
27
- const key = KEY_MAP[ placeholder ];
28
- return siteInformation[ key ] || defaultValue || placeholder;
29
- } );
30
- };
31
-
32
- export default replacePlaceholders;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/starter-page-templates/page-template-modal/utils/tracking.js DELETED
@@ -1,59 +0,0 @@
1
- // Ensure Tracks Library
2
- window._tkq = window._tkq || [];
3
-
4
- let tracksIdentity = null;
5
-
6
- /**
7
- * Populate `identity` on WPCOM and ATOMIC to enable tracking.
8
- * Always disabled for regular self-hosted installations.
9
- */
10
- export const initializeWithIdentity = identity => {
11
- tracksIdentity = identity;
12
- window._tkq.push( [ 'identifyUser', identity.userid, identity.username ] );
13
- };
14
-
15
- export const trackView = ( segment_id, vertical_id ) => {
16
- if ( ! tracksIdentity ) {
17
- return;
18
- }
19
- window._tkq.push( [
20
- 'recordEvent',
21
- 'a8c_full_site_editing_template_selector_view',
22
- {
23
- blog_id: tracksIdentity.blogid,
24
- segment_id,
25
- vertical_id,
26
- },
27
- ] );
28
- };
29
-
30
- export const trackDismiss = ( segment_id, vertical_id ) => {
31
- if ( ! tracksIdentity ) {
32
- return;
33
- }
34
- window._tkq.push( [
35
- 'recordEvent',
36
- 'a8c_full_site_editing_template_selector_dismiss',
37
- {
38
- blog_id: tracksIdentity.blogid,
39
- segment_id,
40
- vertical_id,
41
- },
42
- ] );
43
- };
44
-
45
- export const trackSelection = ( segment_id, vertical_id, template ) => {
46
- if ( ! tracksIdentity ) {
47
- return;
48
- }
49
- window._tkq.push( [
50
- 'recordEvent',
51
- 'a8c_full_site_editing_template_selector_template_selected',
52
- {
53
- blog_id: tracksIdentity.blogid,
54
- segment_id,
55
- vertical_id,
56
- template,
57
- },
58
- ] );
59
- };