assetQueryString->get(); // Defaults for each SCRIPT element. $element_defaults = [ '#type' => 'html_tag', '#tag' => 'script', '#value' => '', ]; // Loop through all JS assets. foreach ($js_assets as $js_asset) { $element = $element_defaults; // Element properties that depend on item type. switch ($js_asset['type']) { case 'setting': $element['#attributes'] = [ // This type attribute prevents this from being parsed as an // inline script. 'type' => 'application/json', 'data-drupal-selector' => 'drupal-settings-json', ]; $element['#value'] = Json::encode($js_asset['data']); break; case 'file': $query_string = $js_asset['version'] == -1 ? $default_query_string : 'v=' . $js_asset['version']; $query_string_separator = str_contains($js_asset['data'], '?') ? '&' : '?'; $element['#attributes']['src'] = $this->fileUrlGenerator->generateString($js_asset['data']); // Only add the cache-busting query string if this isn't an aggregate // file. if (!isset($js_asset['preprocessed'])) { $element['#attributes']['src'] .= $query_string_separator . ($js_asset['cache'] ? $query_string : $this->time->getRequestTime()); } break; case 'external': $element['#attributes']['src'] = $js_asset['data']; break; default: throw new \Exception('Invalid JS asset type.'); } // Attributes may only be set if this script is output independently. if (!empty($element['#attributes']['src']) && !empty($js_asset['attributes'])) { $element['#attributes'] += $js_asset['attributes']; } $elements[] = $element; } return $elements; } }