diff --git a/core/core.services.yml b/core/core.services.yml index 8ce9b11..cf36009 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -1279,6 +1279,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..a2b1f59 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,22 @@ 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 + * + * @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/src/Tests/Theme/EngineTwigTest.php b/core/modules/system/src/Tests/Theme/EngineTwigTest.php index 750ae2e..ff84af7 100644 --- a/core/modules/system/src/Tests/Theme/EngineTwigTest.php +++ b/core/modules/system/src/Tests/Theme/EngineTwigTest.php @@ -111,4 +111,12 @@ public function testTwigFileUrls() { $this->assertRaw('
file_url: ' . $filepath . '
'); } + /** + * Tests the attach of asset libraries. + */ + public function testTwigAttachLibrary() { + $this->drupalGet('/twig-theme-test/attach-library'); + $this->assertRaw('ckeditor.js'); + } + } 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/modules/system/tests/modules/twig_theme_test/src/TwigThemeTestController.php b/core/modules/system/tests/modules/twig_theme_test/src/TwigThemeTestController.php index ff49bd6..50d6c99 100644 --- a/core/modules/system/tests/modules/twig_theme_test/src/TwigThemeTestController.php +++ b/core/modules/system/tests/modules/twig_theme_test/src/TwigThemeTestController.php @@ -69,6 +69,15 @@ public function fileUrlRender() { } /** + * Renders for testing attach_library functions in a Twig template. + */ + public function attachLibraryRender() { + return array( + '#theme' => 'twig_theme_test_attach_library', + ); + } + + /** * Menu callback for testing the Twig registry loader. */ public function registryLoaderRender() { diff --git a/core/modules/system/tests/modules/twig_theme_test/templates/twig_theme_test.attach_library.html.twig b/core/modules/system/tests/modules/twig_theme_test/templates/twig_theme_test.attach_library.html.twig new file mode 100644 index 0000000..0784ab9 --- /dev/null +++ b/core/modules/system/tests/modules/twig_theme_test/templates/twig_theme_test.attach_library.html.twig @@ -0,0 +1 @@ +{{ attach_library('core/ckeditor') }} diff --git a/core/modules/system/tests/modules/twig_theme_test/twig_theme_test.module b/core/modules/system/tests/modules/twig_theme_test/twig_theme_test.module index 7f6fe35..021d039 100644 --- a/core/modules/system/tests/modules/twig_theme_test/twig_theme_test.module +++ b/core/modules/system/tests/modules/twig_theme_test/twig_theme_test.module @@ -50,6 +50,10 @@ function twig_theme_test_theme($existing, $type, $theme, $path) { 'variables' => array(), 'template' => 'twig_theme_test.file_url', ); + $items['twig_theme_test_attach_library'] = array( + 'variables' => array(), + 'template' => 'twig_theme_test.attach_library', + ); return $items; } diff --git a/core/modules/system/tests/modules/twig_theme_test/twig_theme_test.routing.yml b/core/modules/system/tests/modules/twig_theme_test/twig_theme_test.routing.yml index 1001b47..c372c22 100644 --- a/core/modules/system/tests/modules/twig_theme_test/twig_theme_test.routing.yml +++ b/core/modules/system/tests/modules/twig_theme_test/twig_theme_test.routing.yml @@ -40,6 +40,13 @@ twig_theme_test_file_url: requirements: _access: 'TRUE' +twig_theme_test_attach_library: + path: '/twig-theme-test/attach-library' + defaults: + _controller: '\Drupal\twig_theme_test\TwigThemeTestController::attachLibraryRender' + requirements: + _access: 'TRUE' + twig_theme_test_registry_loader: path: '/twig-theme-test/registry-loader' defaults: 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..a273f96 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: { preprocess: false } + 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() }}