diff --git a/core/lib/Drupal/Core/Asset/AssetResolver.php b/core/lib/Drupal/Core/Asset/AssetResolver.php index 7d959d4..89408c9 100644 --- a/core/lib/Drupal/Core/Asset/AssetResolver.php +++ b/core/lib/Drupal/Core/Asset/AssetResolver.php @@ -137,6 +137,16 @@ public function getCssAssets(AttachedAssetsInterface $assets, $optimize) { // Sort CSS items, so that they appear in the correct order. uasort($css, 'static::sort'); + // Allow themes to remove CSS files by CSS files full path and file name. + // @todo Remove in Drupal 9.0.x + if ($stylesheet_remove = $theme_info->getStyleSheetsRemove()) { + foreach ($css as $key => $options) { + if (isset($stylesheet_remove[$key])) { + unset($css[$key]); + } + } + } + if ($optimize) { $css = \Drupal::service('asset.css.collection_optimizer')->optimize($css); } diff --git a/core/lib/Drupal/Core/Asset/LibraryDiscovery.php b/core/lib/Drupal/Core/Asset/LibraryDiscovery.php index bf80a30..bcea7f4 100644 --- a/core/lib/Drupal/Core/Asset/LibraryDiscovery.php +++ b/core/lib/Drupal/Core/Asset/LibraryDiscovery.php @@ -79,7 +79,7 @@ public function getLibraryByName($extension, $name) { $extension = $this->getLibrariesByExtension($extension); if (isset($extension[$name])) { // Handle libraries that are marked for override or removal. - // @see \Drupal\Core\Asset\LibraryDiscoveryParser::applyLibrariesOverrides() + // @see \Drupal\Core\Asset\LibraryDiscoveryParser::applyLibrariesOverride() if (isset($extension[$name]['override'])) { if ($extension[$name]['override']) { list($new_extension, $new_name) = explode('/', $extension[$name]['override']); diff --git a/core/lib/Drupal/Core/Asset/LibraryDiscoveryParser.php b/core/lib/Drupal/Core/Asset/LibraryDiscoveryParser.php index e71dafe..a8048dd 100644 --- a/core/lib/Drupal/Core/Asset/LibraryDiscoveryParser.php +++ b/core/lib/Drupal/Core/Asset/LibraryDiscoveryParser.php @@ -89,7 +89,7 @@ public function buildByExtension($extension) { } $libraries = $this->parseLibraryInfo($extension, $path); - $libraries = $this->applyLibrariesOverrides($libraries, $extension); + $libraries = $this->applyLibrariesOverride($libraries, $extension); foreach ($libraries as $id => &$library) { if (!isset($library['js']) && !isset($library['css']) && !isset($library['drupalSettings'])) { @@ -326,7 +326,7 @@ protected function parseLibraryInfo($extension, $path) { * @return array * The modified libraries definitions. */ - protected function applyLibrariesOverrides($libraries, $extension) { + protected function applyLibrariesOverride($libraries, $extension) { $active_theme = $this->themeManager->getActiveTheme(); $libraries_overrides = $active_theme->getLibrariesOverride(); $theme_path = $active_theme->getPath(); diff --git a/core/lib/Drupal/Core/Theme/ActiveTheme.php b/core/lib/Drupal/Core/Theme/ActiveTheme.php index 73f40af..361ab77 100644 --- a/core/lib/Drupal/Core/Theme/ActiveTheme.php +++ b/core/lib/Drupal/Core/Theme/ActiveTheme.php @@ -60,6 +60,13 @@ class ActiveTheme { protected $extension; /** + * The stylesheets which are set to be removed by the theme. + * + * @var array + */ + protected $styleSheetsRemove; + + /** * The libraries provided by the theme. * * @var array @@ -84,6 +91,7 @@ public function __construct(array $values) { 'path' => '', 'engine' => 'twig', 'owner' => 'twig', + 'stylesheets_remove' => [], 'libraries' => [], 'extension' => 'html.twig', 'base_themes' => [], @@ -94,6 +102,7 @@ public function __construct(array $values) { $this->path = $values['path']; $this->engine = $values['engine']; $this->owner = $values['owner']; + $this->styleSheetsRemove = $values['stylesheets_remove']; $this->libraries = $values['libraries']; $this->extension = $values['extension']; $this->baseThemes = $values['base_themes']; @@ -157,6 +166,17 @@ public function getLibraries() { } /** + * Returns the removed stylesheets by the theme. + * + * @return mixed + * + * @deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0. + */ + public function getStyleSheetsRemove() { + return $this->styleSheetsRemove; + } + + /** * Returns an array of base theme active theme objects keyed by name. * * The order starts with the base theme of $this and ends with the root of @@ -170,6 +190,19 @@ public function getBaseThemes() { /** * Returns the libraries or library assets overridden by the active theme. + * + * The array returned is in the form: + * @code + * [ + * 'core/drupal.collapse' => 'test_theme/collapse', + * 'core/drupal.progress' => FALSE, + * 'classy/base/css/theme/css/layout.css' => 'css/test_theme_layout.css', + * 'core/drupal.dialog/css/theme/misc/dialog.theme.css' => FALSE, + * 'core/jquery/js/assets/vendor/jquery/jquery.min.js' => 'js/collapse.js', + * ] + * @endcode + * + * @return array */ public function getLibrariesOverride() { return $this->librariesOverride; diff --git a/core/lib/Drupal/Core/Theme/ThemeInitialization.php b/core/lib/Drupal/Core/Theme/ThemeInitialization.php index c94826c..a72a3f6 100644 --- a/core/lib/Drupal/Core/Theme/ThemeInitialization.php +++ b/core/lib/Drupal/Core/Theme/ThemeInitialization.php @@ -161,6 +161,9 @@ public function getActiveTheme(Extension $theme, array $base_themes = []) { $values['path'] = $theme_path; $values['name'] = $theme->getName(); + // @todo Remove in Drupal 9.0.x + $values['stylesheets_remove'] = $this->prepareStylesheetsRemove($theme, $base_themes); + // Prepare libraries overrides from this theme and ancestor themes. // This allows child themes to easily remove CSS files from base themes and // modules. @@ -235,8 +238,10 @@ protected function getExtensions() { * * @return string * CSS file where placeholders are replaced. + * + * @todo Remove in Drupal 9.0.x */ - protected function resolveStyleSheetPlaceholders($css_file) { + private function resolveStyleSheetPlaceholders($css_file) { $token_candidate = explode('/', $css_file)[0]; if (!preg_match('/@[A-z0-9_-]+/', $token_candidate)) { return $css_file; @@ -250,4 +255,42 @@ protected function resolveStyleSheetPlaceholders($css_file) { return str_replace($token_candidate, $extensions[$token]->getPath(), $css_file); } } + + /** + * Prepares stylesheets-remove specified in the *.info.yml file. + * + * @param \Drupal\Core\Extension\Extension $theme + * The theme extension object. + * @param \Drupal\Core\Extension\Extension[] $base_themes + * An array of base themes. + * + * @return array + * + * @todo Remove in Drupal 9.0.x + */ + private function prepareStylesheetsRemove(Extension $theme, $base_themes) { + // Prepare stylesheets from this theme as well as all ancestor themes. + // We work it this way so that we can have child themes remove CSS files + // easily from parent. + $stylesheets_remove = array(); + // Grab stylesheets from base theme. + foreach ($base_themes as $base) { + $base_theme_path = $base->getPath(); + if (!empty($base->info['stylesheets-remove'])) { + foreach ($base->info['stylesheets-remove'] as $css_file) { + $css_file = $this->resolveStyleSheetPlaceholders($css_file); + $stylesheets_remove[$css_file] = $css_file; + } + } + } + + // Add stylesheets used by this theme. + if (!empty($theme->info['stylesheets-remove'])) { + foreach ($theme->info['stylesheets-remove'] as $css_file) { + $css_file = $this->resolveStyleSheetPlaceholders($css_file); + $stylesheets_remove[$css_file] = $css_file; + } + } + return $stylesheets_remove; + } } diff --git a/core/modules/system/src/Tests/Asset/LibraryDiscoveryIntegrationTest.php b/core/modules/system/src/Tests/Asset/LibraryDiscoveryIntegrationTest.php index e0ecd90..2f1e6fb 100644 --- a/core/modules/system/src/Tests/Asset/LibraryDiscoveryIntegrationTest.php +++ b/core/modules/system/src/Tests/Asset/LibraryDiscoveryIntegrationTest.php @@ -46,7 +46,7 @@ public function testElementInfoByTheme() { } /** - * Tests that libraries-overrides are applied to library definitions. + * Tests that libraries-override are applied to library definitions. */ public function testLibrariesOverride() { /** @var \Drupal\Core\Theme\ThemeInitializationInterface $theme_initializer */ diff --git a/core/modules/system/src/Tests/Theme/ThemeInfoTest.php b/core/modules/system/src/Tests/Theme/ThemeInfoTest.php index bc3acc9..3d376ed 100644 --- a/core/modules/system/src/Tests/Theme/ThemeInfoTest.php +++ b/core/modules/system/src/Tests/Theme/ThemeInfoTest.php @@ -56,7 +56,7 @@ protected function setUp() { } /** - * Tests stylesheets removed by libraries-override. + * Tests stylesheets-remove. */ function testStylesheets() { $this->themeHandler->install(array('test_basetheme', 'test_subtheme')); diff --git a/core/modules/system/tests/themes/test_basetheme/test_basetheme.info.yml b/core/modules/system/tests/themes/test_basetheme/test_basetheme.info.yml index d545822..dcb1a2f 100644 --- a/core/modules/system/tests/themes/test_basetheme/test_basetheme.info.yml +++ b/core/modules/system/tests/themes/test_basetheme/test_basetheme.info.yml @@ -5,5 +5,5 @@ version: VERSION core: 8.x libraries: - test_basetheme/global-styling -libraries-override: - theme_test/theme_stylesheets_override_and_remove_test/css/base/css/base-remove.css: false +stylesheets-remove: + - '@theme_test/css/base-remove.css' diff --git a/core/modules/system/tests/themes/test_subtheme/test_subtheme.info.yml b/core/modules/system/tests/themes/test_subtheme/test_subtheme.info.yml index bd6a625..6883e5a 100644 --- a/core/modules/system/tests/themes/test_subtheme/test_subtheme.info.yml +++ b/core/modules/system/tests/themes/test_subtheme/test_subtheme.info.yml @@ -6,6 +6,6 @@ core: 8.x base theme: test_basetheme libraries: - test_subtheme/global-styling -libraries-override: - theme_test/theme_stylesheets_override_and_remove_test/css/base/css/sub-remove.css: false - test_basetheme/global-styling/css/base/base-add.sub-remove.css: false +stylesheets-remove: + - '@theme_test/css/sub-remove.css' + - '@test_basetheme/base-add.sub-remove.css' diff --git a/core/tests/Drupal/Tests/Core/Theme/RegistryTest.php b/core/tests/Drupal/Tests/Core/Theme/RegistryTest.php index 3fe4054..71a71f4 100644 --- a/core/tests/Drupal/Tests/Core/Theme/RegistryTest.php +++ b/core/tests/Drupal/Tests/Core/Theme/RegistryTest.php @@ -92,6 +92,7 @@ public function testGetRegistryForModule() { 'path' => 'core/modules/system/tests/themes/test_theme/test_theme.info.yml', 'engine' => 'twig', 'owner' => 'twig', + 'stylesheets_remove' => [], 'libraries_override' => [], 'libraries' => [], 'extension' => '.twig',