core/modules/big_pipe/big_pipe.libraries.yml | 3 ++ core/modules/big_pipe/css/big_pipe.css | 4 ++ core/modules/big_pipe/src/Render/BigPipe.php | 11 ++--- .../src/Render/Placeholder/BigPipeStrategy.php | 52 +++++++++++++++++++++- core/modules/block/src/BlockViewBuilder.php | 17 +++++++ core/modules/comment/src/CommentLazyBuilders.php | 31 +++++++++++++ .../form/form--comment--preview.html.twig | 3 ++ 7 files changed, 113 insertions(+), 8 deletions(-) diff --git a/core/modules/big_pipe/big_pipe.libraries.yml b/core/modules/big_pipe/big_pipe.libraries.yml index 6da49b7..9a49d6a 100644 --- a/core/modules/big_pipe/big_pipe.libraries.yml +++ b/core/modules/big_pipe/big_pipe.libraries.yml @@ -1,5 +1,8 @@ big_pipe: version: VERSION + css: + theme: + css/big_pipe.css: {} js: js/big_pipe.js: {} drupalSettings: diff --git a/core/modules/big_pipe/css/big_pipe.css b/core/modules/big_pipe/css/big_pipe.css new file mode 100644 index 0000000..49b1259 --- /dev/null +++ b/core/modules/big_pipe/css/big_pipe.css @@ -0,0 +1,4 @@ +div[data-big-pipe-placeholder-id] { + -webkit-filter: opacity(0.2) blur(1px); + filter: opacity(0.2) blur(1px); +} diff --git a/core/modules/big_pipe/src/Render/BigPipe.php b/core/modules/big_pipe/src/Render/BigPipe.php index b312d76..0939ae8 100644 --- a/core/modules/big_pipe/src/Render/BigPipe.php +++ b/core/modules/big_pipe/src/Render/BigPipe.php @@ -716,14 +716,11 @@ protected function renderPlaceholder($placeholder, array $placeholder_render_arr * only keep the first occurrence. */ protected function getPlaceholderOrder($html, $placeholders) { - $fragments = explode('', $fragment, 2); - $placeholder_id = $t[0]; - $placeholder_ids[] = $placeholder_id; + $dom = Html::load($html); + $xpath = new \DOMXPath($dom); + foreach ($xpath->query('//span[@data-big-pipe-placeholder-id]') as $node) { + $placeholder_ids[] = Html::escape($node->getAttribute('data-big-pipe-placeholder-id')); } $placeholder_ids = array_unique($placeholder_ids); diff --git a/core/modules/big_pipe/src/Render/Placeholder/BigPipeStrategy.php b/core/modules/big_pipe/src/Render/Placeholder/BigPipeStrategy.php index f967eba..a475ed8 100644 --- a/core/modules/big_pipe/src/Render/Placeholder/BigPipeStrategy.php +++ b/core/modules/big_pipe/src/Render/Placeholder/BigPipeStrategy.php @@ -5,6 +5,7 @@ use Drupal\Component\Utility\Crypt; use Drupal\Component\Utility\Html; use Drupal\Component\Utility\UrlHelper; +use Drupal\Core\Render\Markup; use Drupal\Core\Render\Placeholder\PlaceholderStrategyInterface; use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\Session\SessionConfigurationInterface; @@ -198,8 +199,57 @@ protected static function placeholderIsAttributeSafe($placeholder) { protected static function createBigPipeJsPlaceholder($original_placeholder, array $placeholder_render_array) { $big_pipe_placeholder_id = static::generateBigPipePlaceholderId($original_placeholder, $placeholder_render_array); + $interface_preview = []; + $lazy_builder_as_string = NULL; + + if (isset($placeholder_render_array['#lazy_builder'])) { + $callable = $placeholder_render_array['#lazy_builder'][0]; + if (is_string($callable)) { + $lazy_builder_as_string = $callable; + if (strpos($callable, ':') !== FALSE && strpos($callable, '::') === FALSE) { + try { + $callable = \Drupal::service('controller_resolver')->getControllerFromDefinition($callable . 'Preview'); + } + catch (\InvalidArgumentException $e) {} + } + else { + $callable .= 'Preview'; + } + } + else if (is_array($callable)) { + $lazy_builder_as_string = get_class($callable[0]) . '::' . $callable[1]; + $callable[1] .= 'Preview'; + } + if (is_callable($callable)) { + $interface_preview = call_user_func_array($callable, $placeholder_render_array['#lazy_builder'][1]); + assert('is_array($interface_preview)', "Interface preview for $original_placeholder must be a render array."); + } + + // Add BigPipe interface preview debug output. (If Twig debug is on.) + // @todo inject Twig service. + $twig_service = \Drupal::service('twig'); + if ($twig_service->isDebug()) { + $interface_preview_callback = $lazy_builder_as_string . 'Preview'; + $implemented = is_callable($callable) + ? 'YES! See theme debug output below:' + : 'NO, contact a developer…'; + $info = [ + "", + "", + "", + ]; + $interface_preview = [ + '#prefix' => Markup::create("\n\n " . implode("\n ", $info)), + 'actual interface preview' => $interface_preview, + '#suffix' => Markup::create("\n\n"), + ]; + } + } + return [ - '#markup' => '', + '#prefix' => '', + 'interface preview' => $interface_preview, + '#suffix' => '', '#cache' => [ 'max-age' => 0, 'contexts' => [ diff --git a/core/modules/block/src/BlockViewBuilder.php b/core/modules/block/src/BlockViewBuilder.php index 3b20d7b..6b054ad 100644 --- a/core/modules/block/src/BlockViewBuilder.php +++ b/core/modules/block/src/BlockViewBuilder.php @@ -191,6 +191,23 @@ public static function lazyBuilder($entity_id, $view_mode) { } /** + * Interface preview for ::lazyBuilder(). + */ + public static function lazyBuilderPreview($entity_id) { + $block = Block::load($entity_id); + return [ + '#theme' => 'block', + '#attributes' => [], + '#configuration' => ['provider' => 'preview'], + '#plugin_id' => 'preview__' . $block->getPluginId(), + '#base_plugin_id' => '', + '#derivative_plugin_id' => '', + '#id' => 'preview__' . $entity_id, + 'content' => [], + ]; + } + + /** * #pre_render callback for building a block. * * Renders the content using the provided block plugin, and then: diff --git a/core/modules/comment/src/CommentLazyBuilders.php b/core/modules/comment/src/CommentLazyBuilders.php index 730c840..f223b32 100644 --- a/core/modules/comment/src/CommentLazyBuilders.php +++ b/core/modules/comment/src/CommentLazyBuilders.php @@ -3,6 +3,7 @@ namespace Drupal\comment; use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface; +use Drupal\Component\Utility\Random; use Drupal\Core\Entity\EntityFormBuilderInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityManagerInterface; @@ -111,6 +112,17 @@ public function renderForm($commented_entity_type_id, $commented_entity_id, $fie } /** + * Interface preview for ::renderForm(). + */ + public function renderFormPreview() { + return [ + '#type' => 'form', + '#theme' => 'form__comment__preview', + '#form_id' => 'comment_form_preview', + ]; + } + + /** * #lazy_builder callback; builds a comment's links. * * @param string $comment_entity_id @@ -151,6 +163,25 @@ public function renderLinks($comment_entity_id, $view_mode, $langcode, $is_in_pr } /** + * Interface preview for ::renderLinks(). + */ + public function renderLinksPreview() { + return [ + '#theme' => 'links__comment__preview', + '#pre_render' => ['drupal_pre_render_links'], + '#attributes' => ['class' => ['links', 'inline']], + 'preview' => [ + '#theme' => 'links__node', + '#links' => [ + ['title' => '▆▆▆▆▆', 'url' => Url::fromRoute('')], + ['title' => '▆▆▆▆▆', 'url' => Url::fromRoute('')], + ], + ], + ]; + return $this->renderer->renderPlain($links); + } + + /** * Build the default links (reply, edit, delete …) for a comment. * * @param \Drupal\comment\CommentInterface $entity diff --git a/core/themes/classy/templates/form/form--comment--preview.html.twig b/core/themes/classy/templates/form/form--comment--preview.html.twig new file mode 100644 index 0000000..ec91299 --- /dev/null +++ b/core/themes/classy/templates/form/form--comment--preview.html.twig @@ -0,0 +1,3 @@ +
+
+