Commit 94615a13 authored by alexpott's avatar alexpott

Issue #2510104 by pwolanin, nod_, Fabianx, Wim Leers, droplet, Pere Orga:...

Issue #2510104 by pwolanin, nod_, Fabianx, Wim Leers, droplet, Pere Orga: Convert drupalSettings from JavaScript to JSON, to allow for CSP in the future
parent 9024fa61
......@@ -52,6 +52,10 @@ drupal:
drupalSettings:
version: VERSION
js:
# Need to specify a negative weight like drupal.js until
# https://www.drupal.org/node/1945262 is resolved.
misc/drupalSettingsLoader.js: { weight: -18 }
drupalSettings:
# These placeholder values will be set by system_js_settings_alter().
path:
......
......@@ -51,12 +51,6 @@ public function render(array $js_assets) {
// query-string instead, to enforce reload on every page request.
$default_query_string = $this->state->get('system.css_js_query_string') ?: '0';
// For inline JavaScript to validate as XHTML, all JavaScript containing
// XHTML needs to be wrapped in CDATA. To make that backwards compatible
// with HTML 4, we need to comment out the CDATA-tag.
$embed_prefix = "\n<!--//--><![CDATA[//><!--\n";
$embed_suffix = "\n//--><!]]>\n";
// Defaults for each SCRIPT element.
$element_defaults = array(
'#type' => 'html_tag',
......@@ -73,9 +67,13 @@ public function render(array $js_assets) {
// Element properties that depend on item type.
switch ($js_asset['type']) {
case 'setting':
$element['#value_prefix'] = $embed_prefix;
$element['#value'] = 'var drupalSettings = ' . Json::encode($js_asset['data']) . ";";
$element['#value_suffix'] = $embed_suffix;
$element['#attributes'] = array(
// 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':
......
......@@ -11,14 +11,6 @@
* @prop {number} length=0
*/
/**
* Variable generated by Drupal with all the configuration created from PHP.
*
* @global
*
* @var {object} drupalSettings
*/
/**
* Variable generated by Drupal that holds all translated strings from PHP.
*
......
/**
* @file
* Parse inline JSON and initialize the drupalSettings global object.
*/
(function () {
"use strict";
var settingsElement = document.querySelector('script[type="application/json"][data-drupal-selector="drupal-settings-json"]');
/**
* Variable generated by Drupal with all the configuration created from PHP.
*
* @global
*
* @type {object}
*/
window.drupalSettings = {};
if (settingsElement !== null) {
window.drupalSettings = JSON.parse(settingsElement.textContent);
}
})();
......@@ -66,7 +66,7 @@ protected function setRawContent($content) {
$this->plainTextContent = NULL;
$this->elements = NULL;
$this->drupalSettings = array();
if (preg_match('/var drupalSettings = (.*?);$/m', $content, $matches)) {
if (preg_match('@<script type="application/json" data-drupal-selector="drupal-settings-json">([^<]*)</script>@', $content, $matches)) {
$this->drupalSettings = Json::decode($matches[1]);
}
}
......
......@@ -185,9 +185,9 @@ function testAggregation() {
$rendered_footer_js = \Drupal::service('asset.js.collection_renderer')->render($footer_js);
$this->assertTrue(
count($rendered_footer_js) == 2
&& substr($rendered_footer_js[0]['#value'], 0, 20) === 'var drupalSettings ='
&& $rendered_footer_js[0]['#attributes']['data-drupal-selector'] === 'drupal-settings-json'
&& substr($rendered_footer_js[1]['#attributes']['src'], 0, 7) === 'http://',
'There are 2 JavaScript assets in the footer: one with drupalSettings, one with the sole aggregated JavaScript asset.'
'There are 2 JavaScript assets in the footer: one with drupal settings, one with the sole aggregated JavaScript asset.'
);
}
......@@ -206,9 +206,9 @@ function testSettings() {
$rendered_js = $this->renderer->renderPlain($js_render_array);
// Parse the generated drupalSettings <script> back to a PHP representation.
$startToken = 'drupalSettings = ';
$startToken = '{';
$endToken = '}';
$start = strpos($rendered_js, $startToken) + strlen($startToken);
$start = strpos($rendered_js, $startToken);
$end = strrpos($rendered_js, $endToken);
$json = Unicode::substr($rendered_js, $start, $end - $start + 1);
$parsed_settings = Json::decode($json);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment