core/core.services.yml | 1 + core/lib/Drupal/Core/Template/TwigExtension.php | 41 ++++++++++++++++++++++ .../twig_extension_test.services.yml | 1 + .../Tests/Core/Template/TwigExtensionTest.php | 3 +- core/themes/bartik/bartik.libraries.yml | 7 +++- .../bartik/templates/status-messages.html.twig | 1 + 6 files changed, 52 insertions(+), 2 deletions(-) diff --git a/core/core.services.yml b/core/core.services.yml index ca74a8c..48a3991 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -1212,6 +1212,7 @@ services: - { name: service_collector, tag: 'twig.extension', call: addExtension } twig.extension: class: Drupal\Core\Template\TwigExtension + arguments: ['@renderer'] tags: - { name: twig.extension, priority: 100 } calls: diff --git a/core/lib/Drupal/Core/Template/TwigExtension.php b/core/lib/Drupal/Core/Template/TwigExtension.php index 551e3cb..625aa0e 100644 --- a/core/lib/Drupal/Core/Template/TwigExtension.php +++ b/core/lib/Drupal/Core/Template/TwigExtension.php @@ -12,6 +12,7 @@ namespace Drupal\Core\Template; +use Drupal\Core\Render\RendererInterface; use Drupal\Core\Routing\UrlGeneratorInterface; use Drupal\Core\Url; use Drupal\Core\Utility\LinkGeneratorInterface; @@ -40,10 +41,29 @@ class TwigExtension extends \Twig_Extension { protected $linkGenerator; /** + * The renderer. + * + * @var \Drupal\Core\Render\RendererInterface + */ + protected $renderer; + + /** * Constructs \Drupal\Core\Template\TwigExtension. * + * @param \Drupal\Core\Render\RendererInterface $renderer + * The renderer. + */ + public function __construct(RendererInterface $renderer) { + $this->renderer = $renderer; + } + + /** + * Sets the URL generator. + * * @param \Drupal\Core\Routing\UrlGeneratorInterface $url_generator * The URL generator. + * + * @return $this */ public function setGenerators(UrlGeneratorInterface $url_generator) { $this->urlGenerator = $url_generator; @@ -77,6 +97,7 @@ public function getFunctions() { new \Twig_SimpleFunction('url_from_path', array($this, 'getUrlFromPath'), array('is_safe_callback' => array($this, 'isUrlGenerationSafe'))), new \Twig_SimpleFunction('link', array($this, 'getLink')), new \Twig_SimpleFunction('file_url', 'file_create_url'), + new \Twig_SimpleFunction('attach_library', array($this, 'attachLibrary')) ); } @@ -257,4 +278,24 @@ public function isUrlGenerationSafe(\Twig_Node $args_node) { return array(); } + /** + * Attaches an asset library to the template, and hence to the response. + * + * Allows Twig templates to attach asset libraries using + * @code + * {{ attach_library('extension/library_name') }} + * @endcode + * + * This makes for a much better TX. + * + * @param string $library + * An asset library. + */ + public function attachLibrary($library) { + // Use Renderer::render() on a temporary render array to get additional + // bubbleable metadata on the render stack. + $template_attached = ['#attached' => ['library' => [$library]]]; + $this->renderer->render($template_attached); + } + } diff --git a/core/modules/system/tests/modules/twig_extension_test/twig_extension_test.services.yml b/core/modules/system/tests/modules/twig_extension_test/twig_extension_test.services.yml index 8784c0f..491d1e8 100644 --- a/core/modules/system/tests/modules/twig_extension_test/twig_extension_test.services.yml +++ b/core/modules/system/tests/modules/twig_extension_test/twig_extension_test.services.yml @@ -1,5 +1,6 @@ services: twig_extension_test.twig.test_extension: + arguments: ['@renderer'] class: Drupal\twig_extension_test\TwigExtension\TestExtension tags: - { name: twig.extension } diff --git a/core/tests/Drupal/Tests/Core/Template/TwigExtensionTest.php b/core/tests/Drupal/Tests/Core/Template/TwigExtensionTest.php index 31352a6..3866965 100644 --- a/core/tests/Drupal/Tests/Core/Template/TwigExtensionTest.php +++ b/core/tests/Drupal/Tests/Core/Template/TwigExtensionTest.php @@ -25,13 +25,14 @@ class TwigExtensionTest extends UnitTestCase { * @dataProvider providerTestEscaping */ public function testEscaping($template, $expected) { + $renderer = $this->getMock('\Drupal\Core\Render\RendererInterface'); $twig = new \Twig_Environment(NULL, array( 'debug' => TRUE, 'cache' => FALSE, 'autoescape' => TRUE, 'optimizations' => 0 )); - $twig->addExtension((new TwigExtension())->setGenerators($this->getMock('Drupal\Core\Routing\UrlGeneratorInterface'))); + $twig->addExtension((new TwigExtension($renderer))->setGenerators($this->getMock('Drupal\Core\Routing\UrlGeneratorInterface'))); $nodes = $twig->parse($twig->tokenize($template)); diff --git a/core/themes/bartik/bartik.libraries.yml b/core/themes/bartik/bartik.libraries.yml index 23ba491..f796093 100644 --- a/core/themes/bartik/bartik.libraries.yml +++ b/core/themes/bartik/bartik.libraries.yml @@ -22,7 +22,6 @@ global-styling: css/components/region-help.css: {} css/components/item-list.css: {} css/components/list-group.css: {} - css/components/messages.css: {} css/components/node-preview.css: {} css/components/pager.css: {} css/components/panel.css: {} @@ -46,6 +45,12 @@ global-styling: css/colors.css: {} css/print.css: { media: print } +messages: + version: VERSION + css: + theme: + css/components/messages.css: {} + color.preview: version: VERSION css: diff --git a/core/themes/bartik/templates/status-messages.html.twig b/core/themes/bartik/templates/status-messages.html.twig index a3b5d49..96188d3 100644 --- a/core/themes/bartik/templates/status-messages.html.twig +++ b/core/themes/bartik/templates/status-messages.html.twig @@ -24,6 +24,7 @@ #} {% block messages %} {% if message_list is not empty %} + {{ attach_library('bartik/messages') }}
{{ parent() }}