theming – Cannot get the sub-theme retrieve the CSS files from libraries

I have localized Bulma theme following the instructions which were as simple as creating a new directory called ‘libraries’ under main directory (httpdocs) and putting the sources files in it. No problem with that.

  • I have been trying to create a sub theme which I named “bulma_sub”.

bulma_sub is located under themes’ folder (where the bulma base theme is).

  • there are three files in bulma_sub folder with the following set-up.

bulma_sub.info.yml

name: bulma_sub
description: 'subtheme based on bulma'
type: theme
base theme: bulma
core_version_requirement: ^8.8 || ^9
package: Core

regions:
  header: 'Header'
  navbar_branding: 'Branding'
  navbar_social: 'Social'
  header_search: 'Search'
  header_tabs: 'Tabs'
  primary_menu: 'Primary menu'
  secondary_menu: 'Secondary menu'
  highlighted: 'Highlighted'
  help: 'Help'
  content: 'Content'
  sidebar_first: 'Sidebar First'
  sidebar_second: 'Sidebar Second'
  tile_one: 'Tile 1'
  tile_two: 'Tile 2'
  tile_three: 'Tile 3'
  tile_four: 'Tile 4'
  tile_five: 'Tile 5'
  bottom: 'Bottom'
  footer: 'Footer'

libraries:
  - bulma_sub/global

# Information added by Drupal.org packaging script on 2020-10-27
version: '8.x-1.0-rc1'
project: 'bulma'
datestamp: 1603840308

bulma_sub.libraries.yml

    global:
      css:
        theme:
          css/overrides.css: {}
          css/style.css: {}
      dependencies:
        - core/jquery
        - core/jquery.once
        - core/drupal

bulma_sub.theme file (same as the source file)

<?php

/**
 * @file
 * The primary PHP file for the Drupal Bulma base theme.
 */

use DrupalblockEntityBlock;
use DrupalbulmaBulma;
use DrupalbulmaBulmaswatch;
use DrupalfileEntityFile;

/**
 * Implements template_preprocess_page().
 */
function bulma_preprocess_page(&$variables) {

  // Site slogan as separate variable.
  $site_config = Drupal::config('system.site');
  $variables('site_slogan') = $site_config->get('slogan');
}

/**
 * Implements template_preprocess_file_link().
 */
function bulma_preprocess_file_link(&$variables) {
  /** @var DrupalCoreEntityEntityFile $file */
  $file = ($variables('file') instanceof File) ? $variables('file') : File::load($variables('file')->fid);

  $variables('icon') = Bulma::getFileIcon($file);
}

/**
 * Implements hook_page_attachments_alter().
 */
function bulma_page_attachments_alter(&$page) {

  // Force IE to use Chrome Frame if installed.
  $page('#attached')('html_head')() = (
    (
      '#type' => 'html_tag',
      '#tag' => 'meta',
      '#attributes' => (
        'http-equiv' => 'X-UA-Compatible',
        'content' => 'IE=edge,chrome=1',
      ),
    ),
    'chrome_frame',
  );

  // Remove image toolbar in IE.
  $page('#attached')('html_head')() = (
    (
      '#type' => 'html_tag',
      '#tag' => 'meta',
      '#attributes' => (
        'http-equiv' => 'ImageToolbar',
        'content' => 'false',
      ),
    ),
    'ie_image_toolbar',
  );

  // Alter viewport.
  $page('#attached')('html_head')() = (
    (
      '#type' => 'html_tag',
      '#tag' => 'meta',
      '#attributes' => (
        'name' => 'viewport',
        'content' => 'width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no',
      ),
    ),
    'viewport',
  );
}

/**
 * Implements bulma_preprocess_HOOK() for breadcrumb.
 */
function bulma_preprocess_breadcrumb(&$variables) {
  // Load Bulma class from settings.
  $classes = array_merge(('breadcrumb'), Bulma::multiSettings('breadcrumb'));
  foreach ($classes as $class) {
    $variables('attributes')('class')() = $class;
  }
  $variables('attributes')('role') = 'navigation';
  $variables('attributes')('aria-labelledby') = 'system-breadcrumb';
}

/**
 * Implements theme_menu_local_tasks().
 */
function bulma_preprocess_menu_local_tasks(&$variables) {

  // Load Bulma class from settings.
  $bulma_tabs_class = Bulma::multiSettings('tabs');

  if (!empty($bulma_tabs_class)) {
    // Set variables.
    foreach ($bulma_tabs_class as $key => $class) {
      $variables(str_replace('is-', '', $key)) = $class;
    }

  }

}

/**
 * Implements hook_form_alter().
 */
function bulma_form_alter(&$form, $form_state, $form_id) {

  // Check for actions buttons, group them.
  if (isset($form('actions'))) {
    $form('actions')('#attributes')('class')() = 'field';
    $form('actions')('#attributes')('class')() = 'is-grouped';

    // Loop trough array to get link type.
    // Better approach maybe to use https://www.drupal.org/project/button_link.
    foreach ($form('actions') as $key => $action) {
      if (isset($action('#type'))) {
        if ($action('#type') == 'link') {
          $name = (string) $action('#title');

          // Check if button should be colorized.
          $button_color = Bulma::colorizeButton($name);

          // Add button class.
          if (!empty($button_color)) {
            foreach ($button_color as $class) {
              $form('actions')($key)('#attributes')('class')() = $class;
            }
          }
        }

      }
    }
  }

  switch ($form_id) {
    case 'node_preview_form_select':
      $form('backlink')('#options')('attributes')('class')() = 'button';
      break;
  }

}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function bulma_form_search_form_alter(&$form, $form_state, $form_id) {

  // Remove label.
  $form('basic')('keys')('#title_display') = 'invisible';

  // Update the placeholder.
  $form('basic')('keys')('#placeholder') = t('Enter your keywords');

  // Wrap class to combine form.
  $form('basic')('#attributes')('class') = 'field has-addons';

}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function bulma_form_search_block_form_alter(&$form, $form_state, $form_id) {

  // Update the placeholder, remove title - prevent double icon.
  $form('keys')('#title') = '';
  $form('keys')('#placeholder') = t('Search');

}

/**
 * Implements hook_theme_suggestions_HOOK_alter().
 */
function bulma_theme_suggestions_form_alter(array &$suggestions, array $variables) {
  if ($variables('element')('#form_id') === 'search_block_form') {
    $suggestions() = 'form__search_block_form';
  }
}

/**
 * Implements template_preprocess_block().
 */
function bulma_preprocess_block(&$variables) {

  // Block as panel style.
  if (Bulma::singleSetting('general.block')) {
    if ($variables('configuration')('label_display')) {
      $variables('block_panel_style') = TRUE;
    }
  }

  // Customize the ID and classes of the main menu block.
  $main_menu = Bulma::singleSetting('general.menu');
  $plugin_id = 'system_menu_block:' . $main_menu;
  // Match blocks by plugin ID to support Bulma and any active subtheme.
  if (!empty($variables('elements')('#plugin_id')) && $variables('elements')('#plugin_id') == $plugin_id) {
    $variables('attributes')('id') = 'navbar-menu';
    $variables('attributes')('class')() = 'navbar-end';
  }

  // Set a region variable for use in templates.
  if (isset($variables('elements')('#id'))) {
    $block = Block::load($variables('elements')('#id'));
    $variables('region') = $block->getRegion();
  }
}

/**
 * Implements template_preprocess_table().
 */
function bulma_preprocess_table(&$variables) {
  // Load existing classes.
  $existing_class = ();
  if (isset($variables('attributes')('class'))) {
    $existing_class = $variables('attributes')('class');
  }

  // Load Bulma specific table classes from theme settings.
  $bulma_table_class = Bulma::multiSettings('table');

  // Merge classes.
  if (!empty($bulma_table_class)) {
    $variables('attributes')('class') = array_merge($existing_class, $bulma_table_class);
  }

}

/**
 * Implements hook_theme_suggestions_HOOK_alter().
 */
function bulma_theme_suggestions_links_alter(array &$suggestions, array $variables) {
  $link_type = $variables('theme_hook_original');

  // We want only affect node and comment links.
  $target_output = ('links__node', 'links__comment');

  if (in_array($link_type, $target_output)) {
    $suggestions() = 'links__bulma';
  }

}

/**
 * Implements hook_theme_suggestions_HOOK_alter().
 */
function bulma_theme_suggestions_input_alter(array &$suggestions, array $variables) {

  // Define defaults for exclusion for rendering as bulma input.
  $exclude_input = (
    'hidden',
    'token',
    'radio',
    'checkbox',
    'submit',
    'image_button',
  );

  // Submit button needs have render as button element.
  if ($variables('element')('#type') == 'submit') {
    $suggestions() = 'input__button__bulma';
  }

  // Add theme suggestions for others input elements.
  if (!in_array($variables('element')('#type'), $exclude_input)) {

    // Default wrapped input.
    $suggestions() = 'input__bulma';
  }

}

/**
 * Implements template_preprocess_hook().
 */
function bulma_preprocess_input__bulma(&$variables) {
  // Make sure we have data to work from.
  if (empty($variables('element')('#type')) || empty($variables('element')('#title'))) {
    return;
  }
  // Field name and type.
  $type = $variables('element')('#type');
  $name = (string) $variables('element')('#title');

  // Check if we use icons.
  if (Bulma::singleSetting('general.icon')) {
    $variables('icon') = Bulma::iconMatch($name, $type);

  }

  // Size of input buttons.
  $input_size = Bulma::singleSetting('bulma_elements_input_size');

  if ($input_size != 'none') {
    $variables('attributes')('class')() = $input_size;
  }

}

/**
 * Implements template_preprocess_hook().
 */
function bulma_preprocess_input__button__bulma(&$variables) {

  // Field name and type.
  $name = $variables('element')('#value');
  $type = $variables('element')('#type');

  // We need render label inside button tag.
  $variables('label') = $variables('element')('#value');

  // Bulma submit classes.
  $variables('bulma_button_classes') = ();

  // Check if button should be colorized.
  $button_color = Bulma::colorizeButton($name);

  if (!empty($button_color)) {
    $variables('bulma_button_classes') = $button_color;
  }

  // Check if we use icons.
  if (Bulma::singleSetting('general.icon')) {
    // Define default if not matched.
    $variables('icon') = Bulma::iconMatch($name, $type);

    // Hide label for search button.
    if ($variables('icon') == 'search') {
      $variables('label') = FALSE;
    }
  }

}

/**
 * Implements hook_theme_suggestions_HOOK_alter().
 */
function bulma_theme_suggestions_menu_alter(array &$suggestions, array $variables) {

  // Navbar menu.
  $bulma_nav = Bulma::singleSetting('general.menu');

  // Check if any menu is selected to be nav menu.
  if ($bulma_nav != 'none') {
    if ($variables('menu_name') === $bulma_nav) {
      $suggestions() = 'menu__nav_bulma';
    }
  }

}

/**
 * Implements template_preprocess_form_element().
 */
function bulma_preprocess_form_element(&$variables) {

  // Render the form element inside the label for checkbox and radio.
  if (in_array($variables('element')('#type'), ('checkbox', 'radio'))) {
    $variables('label')('#children') = $variables('children');
    unset($variables('children'));
  }

}

/**
 * Implements template_preprocess_form_element_label().
 */
function bulma_preprocess_form_element_label(&$variables) {

  // Check additional theme labels settings.
  $bulma_labels = Bulma::multiSettings('label');

  if (!empty($bulma_labels)) {
    foreach ($bulma_labels as $key => $value) {
      $variables($key) = $value;
    }
  }

}

/**
 * Implements template_preprocess_page_title().
 */
function bulma_preprocess_page_title(&$variables) {
  $variables('title_attributes')('class') = 'title';
}

/**
 * Implements template_preprocess_views_view_table().
 */
function bulma_preprocess_views_view_table(&$variables) {

  // Define defaults for variables.
  $variables('bordered') = FALSE;
  $variables('striped') = FALSE;
  $variables('narrow') = FALSE;
  $variables('table') = TRUE;

  // Load Bulma specific table classes from theme settings.
  $bulma_table_class = Bulma::multiSettings('table');

  if (!empty($bulma_table_class)) {
    foreach ($bulma_table_class as $class) {
      $variables(str_replace('is-', '', $class)) = TRUE;
    }
  }
}

/**
 * Implements hook_library_info_alter().
 */
function bulma_library_info_alter(&$libraries, $extension) {
  // Swap in Bulmaswatch theme's CSS.
  if ($extension === 'bulma' &&
    isset($libraries('global')) &&
    ($theme = theme_get_setting('cdn.bulmaswatch.theme'))
  ) {
    // If bulmaswatch is configured to use the default theme, use Bulma directly.
    $cdn_data = Bulma::getCdnData();
    $properties = ();
    if ($theme === 'default') {
      $bulma_file = '/css/bulma.css';
      if (Bulma::isLocal()) {
        $css_file = '/libraries/bulma' . $bulma_file;
      }
      else {
        $css_file = $cdn_data('api')('bulma')('file_root') . $bulma_file;
        $properties('type') = 'external';
      }
    }
    else {
      $properties('minified') = TRUE;
      $themes = Bulmaswatch::getThemes();
      if (isset($themes($theme)('local_css'))) {
        $css_file = $themes($theme)('local_css');
      }
      else {
        $css_file = $cdn_data('api')('bulmaswatch')('file_root') . "/{$theme}/bulmaswatch.min.css";
        $properties('type') = 'external';
      }
    }
    $libraries('global')('css')('base') = (
      $css_file => $properties,
    );
  }

}

File structure

libraries
|_bulma
  |_css
    |_bulma.css
  |_sass

themes
|_bulma
  |_assets
    |_bulma.style.css
    |_bulma.style.scss
    |_overrides.css
    |_overrides
|_bulma_sub
  |_css
    |_overrides.css
    |_style.css

The sites shows up without any css applied. And also the Home link is duplicated. Any ideas?

And I get this error

Fatal error: Cannot redeclare bulma_library_info_alter() (previously
declared in
C:UsersY430Sitesdevdesktopdrupal-8.9.1themesbulmabulma.theme:416)
in
C:UsersY430Sitesdevdesktopdrupal-8.9.1themesbulma_subbulma_sub.theme
on line 416

if I copy bulma.theme file to bulma_sub folder. I didn’t face such issue when I created a sub-theme based on bootstraps before!