summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathaniel Catchpole2017-06-29 12:52:16 +0100
committerNathaniel Catchpole2017-06-29 12:52:16 +0100
commit31a3fe830c3ddcafb3d4597e502ebef39b1b2dd6 (patch)
treed3d0b5677b38edb1ca7ef48c385b9f03a51706c2
parentda86c03cfbcf16ea722ecb0cdcf6631cb37cfeba (diff)
Issue #2694535 by WidgetsBurritos, samuel.mortenson, Manuel Garcia, idebr, tstoeckler, metzlerd, larowlan: Support rect property and nested render arrays in html_tag for dynamic SVGs
-rw-r--r--core/lib/Drupal/Core/Render/Element/HtmlTag.php23
-rw-r--r--core/tests/Drupal/KernelTests/KernelTestBaseTest.php2
-rw-r--r--core/tests/Drupal/Tests/Core/Render/Element/HtmlTagTest.php118
3 files changed, 130 insertions, 13 deletions
diff --git a/core/lib/Drupal/Core/Render/Element/HtmlTag.php b/core/lib/Drupal/Core/Render/Element/HtmlTag.php
index 0b9ac91..2413784 100644
--- a/core/lib/Drupal/Core/Render/Element/HtmlTag.php
+++ b/core/lib/Drupal/Core/Render/Element/HtmlTag.php
@@ -41,6 +41,7 @@ class HtmlTag extends RenderElement {
static protected $voidElements = [
'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input',
'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr',
+ 'rect', 'circle', 'polygon', 'ellipse', 'stop', 'use', 'path',
];
/**
@@ -59,7 +60,7 @@ class HtmlTag extends RenderElement {
}
/**
- * Pre-render callback: Renders a generic HTML tag with attributes into #markup.
+ * Pre-render callback: Renders a generic HTML tag with attributes.
*
* @param array $element
* An associative array containing:
@@ -84,21 +85,27 @@ class HtmlTag extends RenderElement {
// An HTML tag should not contain any special characters. Escape them to
// ensure this cannot be abused.
$escaped_tag = HtmlUtility::escape($element['#tag']);
- $markup = '<' . $escaped_tag . $attributes;
+ $open_tag = '<' . $escaped_tag . $attributes;
+ $close_tag = '</' . $escaped_tag . ">\n";
+ $prefix = isset($element['#prefix']) ? $element['#prefix'] . $open_tag : $open_tag;
+ $suffix = isset($element['#suffix']) ? $close_tag . $element['#suffix'] : $close_tag;
// Construct a void element.
if (in_array($element['#tag'], self::$voidElements)) {
- $markup .= " />\n";
+ $prefix .= " />\n";
+ $suffix = '';
}
// Construct all other elements.
else {
- $markup .= '>';
- $markup .= $element['#value'] instanceof MarkupInterface ? $element['#value'] : Xss::filterAdmin($element['#value']);
- $markup .= '</' . $escaped_tag . ">\n";
+ $prefix .= '>';
+ $markup = $element['#value'] instanceof MarkupInterface ? $element['#value'] : Xss::filterAdmin($element['#value']);
+ $element['#markup'] = Markup::create($markup);
}
if (!empty($element['#noscript'])) {
- $markup = "<noscript>$markup</noscript>";
+ $prefix = '<noscript>' . $prefix;
+ $suffix .= '</noscript>';
}
- $element['#markup'] = Markup::create($markup);
+ $element['#prefix'] = Markup::create($prefix);
+ $element['#suffix'] = Markup::create($suffix);
return $element;
}
diff --git a/core/tests/Drupal/KernelTests/KernelTestBaseTest.php b/core/tests/Drupal/KernelTests/KernelTestBaseTest.php
index 8ec7c54..60c2ce3 100644
--- a/core/tests/Drupal/KernelTests/KernelTestBaseTest.php
+++ b/core/tests/Drupal/KernelTests/KernelTestBaseTest.php
@@ -182,7 +182,7 @@ class KernelTestBaseTest extends KernelTestBase {
$output = \Drupal::service('renderer')->renderRoot($build);
$this->assertEquals('core', \Drupal::theme()->getActiveTheme()->getName());
- $this->assertEquals($expected, $build['#children']);
+ $this->assertEquals($expected, $build['#markup']);
$this->assertEquals($expected, $output);
}
diff --git a/core/tests/Drupal/Tests/Core/Render/Element/HtmlTagTest.php b/core/tests/Drupal/Tests/Core/Render/Element/HtmlTagTest.php
index 46dd91a..713da2f 100644
--- a/core/tests/Drupal/Tests/Core/Render/Element/HtmlTagTest.php
+++ b/core/tests/Drupal/Tests/Core/Render/Element/HtmlTagTest.php
@@ -3,14 +3,14 @@
namespace Drupal\Tests\Core\Render\Element;
use Drupal\Core\Render\Markup;
-use Drupal\Tests\UnitTestCase;
+use Drupal\Tests\Core\Render\RendererTestBase;
use Drupal\Core\Render\Element\HtmlTag;
/**
* @coversDefaultClass \Drupal\Core\Render\Element\HtmlTag
* @group Render
*/
-class HtmlTagTest extends UnitTestCase {
+class HtmlTagTest extends RendererTestBase {
/**
* @covers ::getInfo
@@ -29,8 +29,12 @@ class HtmlTagTest extends UnitTestCase {
*/
public function testPreRenderHtmlTag($element, $expected) {
$result = HtmlTag::preRenderHtmlTag($element);
- $this->assertArrayHasKey('#markup', $result);
- $this->assertEquals($expected, $result['#markup']);
+ foreach ($result as &$child) {
+ if (is_array($child) && isset($child['#tag'])) {
+ $child = HtmlTag::preRenderHtmlTag($child);
+ }
+ }
+ $this->assertEquals($expected, (string) $this->renderer->renderRoot($result));
}
/**
@@ -92,6 +96,112 @@ class HtmlTagTest extends UnitTestCase {
];
$tags[] = [$element, "<p>value</p>\n"];
+ // Ensure that nested render arrays render properly.
+ $element = [
+ '#tag' => 'p',
+ '#value' => NULL,
+ [
+ ['#markup' => '<b>value1</b>'],
+ ['#markup' => '<b>value2</b>'],
+ ],
+ ];
+ $tags[] = [$element, "<p><b>value1</b><b>value2</b></p>\n"];
+
+ // Ensure svg elements.
+ $element = [
+ '#tag' => 'rect',
+ '#attributes' => [
+ 'width' => 25,
+ 'height' => 25,
+ 'x' => 5,
+ 'y' => 10,
+ ],
+ ];
+ $tags[] = [$element, '<rect width="25" height="25" x="5" y="10" />' . "\n"];
+
+ $element = [
+ '#tag' => 'circle',
+ '#attributes' => [
+ 'cx' => 100,
+ 'cy' => 100,
+ 'r' => 100,
+ ],
+ ];
+ $tags[] = [$element, '<circle cx="100" cy="100" r="100" />' . "\n"];
+
+ $element = [
+ '#tag' => 'polygon',
+ '#attributes' => [
+ 'points' => '60,20 100,40 100,80 60,100 20,80 20,40',
+ ],
+ ];
+ $tags[] = [$element, '<polygon points="60,20 100,40 100,80 60,100 20,80 20,40" />' . "\n"];
+
+ $element = [
+ '#tag' => 'ellipse',
+ '#attributes' => [
+ 'cx' => 60,
+ 'cy' => 60,
+ 'rx' => 50,
+ 'ry' => 25,
+ ],
+ ];
+ $tags[] = [$element, '<ellipse cx="60" cy="60" rx="50" ry="25" />' . "\n"];
+
+ $element = [
+ '#tag' => 'use',
+ '#attributes' => [
+ 'x' => 50,
+ 'y' => 10,
+ 'width' => 50,
+ 'height' => 50,
+ ],
+ ];
+ $tags[] = [$element, '<use x="50" y="10" width="50" height="50" />' . "\n"];
+
+ $element = [
+ '#tag' => 'path',
+ '#attributes' => [
+ 'd' => 'M 100 100 L 300 100 L 200 300 z',
+ 'fill' => 'orange',
+ 'stroke' => 'black',
+ 'stroke-width' => 3,
+ ],
+ ];
+ $tags[] = [$element, '<path d="M 100 100 L 300 100 L 200 300 z" fill="orange" stroke="black" stroke-width="3" />' . "\n"];
+
+ $element = [
+ '#tag' => 'stop',
+ '#attributes' => [
+ 'offset' => '5%',
+ 'stop-color' => '#F60',
+ ],
+ ];
+ $tags[] = [$element, '<stop offset="5%" stop-color="#F60" />' . "\n"];
+
+ // Nested svg elements.
+ $element = [
+ '#tag' => 'linearGradient',
+ '#value' => NULL,
+ [
+ '#tag' => 'stop',
+ '#value' => NULL,
+ '#attributes' => [
+ 'offset' => '5%',
+ 'stop-color' => '#F60',
+ ],
+ ],
+ [
+ '#tag' => 'stop',
+ '#value' => NULL,
+ '#attributes' => [
+ 'offset' => '95%',
+ 'stop-color' => '#FF6',
+ ],
+ ],
+ ];
+ $tags[] = [$element, '<linearGradient><stop offset="5%" stop-color="#F60" />' . "\n" . '<stop offset="95%" stop-color="#FF6" />' . "\n" . '</linearGradient>' . "\n"];
+
return $tags;
}