From e6f0b5a48d98e00e4ecda7cdd6bd59b1f04ea70a Mon Sep 17 00:00:00 2001 From: James Johnston Date: Sat, 15 Jul 2017 02:08:32 -0700 Subject: [PATCH] Enable AssetProvider to support inline assets (#338) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add new inline_css, inline_js, and inline_head keys on the AssetProvider::getAssets() function. This allows us to support collectors that require static assets that are not actually saved to a file. Then, update all the asset functions in JavascriptRenderer to support these new keys. An initial use case for this is supporting the HtmlDumper in Symfony’s VarDumper. HtmlDumper only provides the styles and scripts in inline HTML form. The static assets can be customized based on some configuration properties available on the HtmlDumper class. One can actually view the CSS/JS as a long PHP string/heredoc embedded in the HtmlDumper.php source code. They are only accessible via the getDumpHeader function, which returns the CSS/JS in a combined HTML string. --- docs/data_collectors.md | 40 ++++- docs/rendering.md | 17 +- src/DebugBar/DataCollector/AssetProvider.php | 15 ++ src/DebugBar/JavascriptRenderer.php | 169 ++++++++++++++---- .../DebugBar/Tests/JavascriptRendererTest.php | 35 +++- 5 files changed, 215 insertions(+), 61 deletions(-) diff --git a/docs/data_collectors.md b/docs/data_collectors.md index 512d43c..d586f11 100644 --- a/docs/data_collectors.md +++ b/docs/data_collectors.md @@ -71,16 +71,31 @@ in `JavascriptRenderer::addControl($name, $options)` (see Rendering chapter). This will have the result of adding a new indicator to the debug bar. -When implementing the Renderable interface, you may use widgets which are not provided +When implementing the `Renderable` interface, you may use widgets which are not provided with the default install. You can add new assets by implementing the `DebugBar\DataCollector\AssetProvider` interface. -to implement it, you must define the `getAssets()` method. It must return an array with the +To implement it, you must define the `getAssets()` method. It must return an array with the following keys: - - base\_path: base path of assets (optional, if omitted or null, will use the base path of the JavascriptRenderer) - - base\_url: base url of assets (optional, same as base\_path) - - css: an array of css filenames - - js: an array of javascript filenames + - `base_path`: base path of assets (optional, if omitted or null, will use the base path of the `JavascriptRenderer`) + - `base_url`: base url of assets (optional, same as `base_path`) + - `css`: an array of css filenames + - `js`: an array of javascript filenames + - `inline_css`: an array map of content ID to inline CSS content (not including `' . "\n", $content); + } + foreach ($jsFiles as $file) { $html .= sprintf('' . "\n", $file); } + foreach ($inlineJs as $content) { + $html .= sprintf('' . "\n", $content); + } + + foreach ($inlineHead as $content) { + $html .= $content . "\n"; + } + if ($this->enableJqueryNoConflict && !$this->useRequireJs) { $html .= '' . "\n"; } diff --git a/tests/DebugBar/Tests/JavascriptRendererTest.php b/tests/DebugBar/Tests/JavascriptRendererTest.php index f224871..84fe748 100644 --- a/tests/DebugBar/Tests/JavascriptRendererTest.php +++ b/tests/DebugBar/Tests/JavascriptRendererTest.php @@ -64,14 +64,25 @@ class JavascriptRendererTest extends DebugBarTestCase public function testAddAssets() { - $this->r->addAssets('foo.css', 'foo.js', '/bar', '/foobar'); + // Use a loop to test deduplication of assets + for ($i = 0; $i < 2; ++$i) { + $this->r->addAssets('foo.css', 'foo.js', '/bar', '/foobar'); + $this->r->addInlineAssets(array('Css' => 'CssTest'), array('Js' => 'JsTest'), array('Head' => 'HeaderTest')); + } - list($css, $js) = $this->r->getAssets(); + // Make sure all the right assets are returned by getAssets + list($css, $js, $inline_css, $inline_js, $inline_head) = $this->r->getAssets(); $this->assertContains('/bar/foo.css', $css); $this->assertContains('/bar/foo.js', $js); + $this->assertEquals(array('Css' => 'CssTest'), $inline_css); + $this->assertEquals(array('Js' => 'JsTest'), $inline_js); + $this->assertEquals(array('Head' => 'HeaderTest'), $inline_head); + + // Make sure asset files are deduplicated + $this->assertCount(count(array_unique($css)), $css); + $this->assertCount(count(array_unique($js)), $js); $html = $this->r->renderHead(); - //$this->assertTag(array('tag' => 'script', 'attributes' => array('src' => '/foobar/foo.js')), $html); $this->assertContains('', $html); } @@ -90,13 +101,23 @@ class JavascriptRendererTest extends DebugBarTestCase public function testRenderHead() { - $html = $this->r->renderHead(); - $this->assertContains('', $html); - $this->assertTrue(strpos($html, "jQuery.noConflict(true);") > -1); + $this->r->addInlineAssets(array('Css' => 'CssTest'), array('Js' => 'JsTest'), array('Head' => 'HeaderTest')); + $html = $this->r->renderHead(); + // Check for file links + $this->assertContains('', $html); + $this->assertContains('', $html); + // Check for inline assets + $this->assertContains('', $html); + $this->assertContains('', $html); + $this->assertContains('HeaderTest', $html); + // Check jQuery noConflict + $this->assertContains('jQuery.noConflict(true);', $html); + + // Check for absence of jQuery noConflict $this->r->setEnableJqueryNoConflict(false); $html = $this->r->renderHead(); - $this->assertFalse(strpos($html, "jQuery.noConflict(true);")); + $this->assertNotContains('noConflict', $html); } public function testRenderFullInitialization()