[FEATURE] Add .inline property to includeCSS/includeCSSLibs 77/53077/10
authorRaphael Graf <graf@netvertising.ch>
Sat, 3 Jun 2017 10:49:34 +0000 (12:49 +0200)
committerSusanne Moog <susanne.moog@typo3.org>
Mon, 14 Aug 2017 12:00:23 +0000 (14:00 +0200)
If .inline is set, the contents of the css-file is inlined
using <style>-tags.

.inline implies .excludeFromConcatenation.
.import takes precedence over .inline.
The other properties of includeCSS still work if .inline is set.

Resolves: #81223
Releases: master
Change-Id: Id08fb0ce201d6992f68a1ac3f9d7735483cee3d7
Reviewed-on: https://review.typo3.org/53077
Reviewed-by: Henning Liebe <h.liebe@neusta.de>
Tested-by: Henning Liebe <h.liebe@neusta.de>
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Susanne Moog <susanne.moog@typo3.org>
Tested-by: Susanne Moog <susanne.moog@typo3.org>
typo3/sysext/core/Classes/Page/PageRenderer.php
typo3/sysext/core/Documentation/Changelog/master/Feature-81223-IncludeCSSinlineProperty.rst [new file with mode: 0644]
typo3/sysext/frontend/Classes/Page/PageGenerator.php
typo3/sysext/t3editor/Resources/Private/tsref.xml

index 7b92430..ad556e1 100644 (file)
@@ -1354,8 +1354,9 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface
      * @param string $allWrap
      * @param bool $excludeFromConcatenation
      * @param string $splitChar The char used to split the allWrap value, default is "|"
+     * @param bool $inline
      */
-    public function addCssFile($file, $rel = 'stylesheet', $media = 'all', $title = '', $compress = true, $forceOnTop = false, $allWrap = '', $excludeFromConcatenation = false, $splitChar = '|')
+    public function addCssFile($file, $rel = 'stylesheet', $media = 'all', $title = '', $compress = true, $forceOnTop = false, $allWrap = '', $excludeFromConcatenation = false, $splitChar = '|', $inline = false)
     {
         if (!isset($this->cssFiles[$file])) {
             $this->cssFiles[$file] = [
@@ -1367,7 +1368,8 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface
                 'forceOnTop' => $forceOnTop,
                 'allWrap' => $allWrap,
                 'excludeFromConcatenation' => $excludeFromConcatenation,
-                'splitChar' => $splitChar
+                'splitChar' => $splitChar,
+                'inline' => $inline
             ];
         }
     }
@@ -1384,8 +1386,9 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface
      * @param string $allWrap
      * @param bool $excludeFromConcatenation
      * @param string $splitChar The char used to split the allWrap value, default is "|"
+     * @param bool $inline
      */
-    public function addCssLibrary($file, $rel = 'stylesheet', $media = 'all', $title = '', $compress = true, $forceOnTop = false, $allWrap = '', $excludeFromConcatenation = false, $splitChar = '|')
+    public function addCssLibrary($file, $rel = 'stylesheet', $media = 'all', $title = '', $compress = true, $forceOnTop = false, $allWrap = '', $excludeFromConcatenation = false, $splitChar = '|', $inline = false)
     {
         if (!isset($this->cssLibs[$file])) {
             $this->cssLibs[$file] = [
@@ -1397,7 +1400,8 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface
                 'forceOnTop' => $forceOnTop,
                 'allWrap' => $allWrap,
                 'excludeFromConcatenation' => $excludeFromConcatenation,
-                'splitChar' => $splitChar
+                'splitChar' => $splitChar,
+                'inline' => $inline
             ];
         }
     }
@@ -2191,17 +2195,7 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface
         $cssFiles = '';
         if (!empty($this->cssLibs)) {
             foreach ($this->cssLibs as $file => $properties) {
-                $file = $this->getStreamlinedFileName($file);
-                $tag = '<link rel="' . htmlspecialchars($properties['rel'])
-                    . '" type="text/css" href="' . htmlspecialchars($file)
-                    . '" media="' . htmlspecialchars($properties['media']) . '"'
-                    . ($properties['title'] ? ' title="' . htmlspecialchars($properties['title']) . '"' : '')
-                    . $this->endingSlash . '>';
-                if ($properties['allWrap']) {
-                    $wrapArr = explode($properties['splitChar'] ?: '|', $properties['allWrap'], 2);
-                    $tag = $wrapArr[0] . $tag . $wrapArr[1];
-                }
-                $tag .= LF;
+                $tag = $this->createCssTag($properties, $file);
                 if ($properties['forceOnTop']) {
                     $cssFiles = $tag . $cssFiles;
                 } else {
@@ -2222,17 +2216,7 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface
         $cssFiles = '';
         if (!empty($this->cssFiles)) {
             foreach ($this->cssFiles as $file => $properties) {
-                $file = $this->getStreamlinedFileName($file);
-                $tag = '<link rel="' . htmlspecialchars($properties['rel'])
-                    . '" type="text/css" href="' . htmlspecialchars($file)
-                    . '" media="' . htmlspecialchars($properties['media']) . '"'
-                    . ($properties['title'] ? ' title="' . htmlspecialchars($properties['title']) . '"' : '')
-                    . $this->endingSlash . '>';
-                if ($properties['allWrap']) {
-                    $wrapArr = explode($properties['splitChar'] ?: '|', $properties['allWrap'], 2);
-                    $tag = $wrapArr[0] . $tag . $wrapArr[1];
-                }
-                $tag .= LF;
+                $tag = $this->createCssTag($properties, $file);
                 if ($properties['forceOnTop']) {
                     $cssFiles = $tag . $cssFiles;
                 } else {
@@ -2243,6 +2227,34 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface
         return $cssFiles;
     }
 
+    /**
+     * Create link (inline=0) or style (inline=1) tag
+     *
+     * @param array $properties
+     * @param string $file
+     * @return string
+     */
+    private function createCssTag(array $properties, string $file): string
+    {
+        if ($properties['inline'] && @is_file($file)) {
+            $tag = $this->createInlineCssTagFromFile($file, $properties);
+        } else {
+            $href = $this->getStreamlinedFileName($file);
+            $tag = '<link rel="' . htmlspecialchars($properties['rel'])
+                . '" type="text/css" href="' . htmlspecialchars($href)
+                . '" media="' . htmlspecialchars($properties['media']) . '"'
+                . ($properties['title'] ? ' title="' . htmlspecialchars($properties['title']) . '"' : '')
+                . $this->endingSlash . '>';
+        }
+        if ($properties['allWrap']) {
+            $wrapArr = explode($properties['splitChar'] ?: '|', $properties['allWrap'], 2);
+            $tag = $wrapArr[0] . $tag . $wrapArr[1];
+        }
+        $tag .= LF;
+
+        return $tag;
+    }
+
     /**
      * Render inline CSS
      *
@@ -2783,4 +2795,24 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface
             }
         }
     }
+
+    /**
+     * Creates an CSS inline tag
+     *
+     * @param string $file the filename to process
+     * @param array $properties
+     * @return string
+     */
+    protected function createInlineCssTagFromFile(string $file, array $properties): string
+    {
+        $cssInline = file_get_contents($file);
+
+        return '<style type="text/css"'
+            . ' media="' . htmlspecialchars($properties['media']) . '"'
+            . ($properties['title'] ? ' title="' . htmlspecialchars($properties['title']) . '"' : '')
+            . '>' . LF
+            . '/*<![CDATA[*/' . LF . '<!-- ' . LF
+            . $cssInline
+            . '-->' . LF . '/*]]>*/' . LF . '</style>' . LF;
+    }
 }
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-81223-IncludeCSSinlineProperty.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-81223-IncludeCSSinlineProperty.rst
new file mode 100644 (file)
index 0000000..036288a
--- /dev/null
@@ -0,0 +1,40 @@
+.. include:: ../../Includes.txt
+
+=================================================
+Feature: #81223 - includeCSS.inline property
+=================================================
+
+See :issue:`81223`
+
+Description
+===========
+
+A property :ts:`.inline` has been added to :ts:`page.includeCSS`. 
+If :ts:`.inline` is set, the content of the css-file is inlined using <style>-tags.
+
+
+Impact
+======
+
+Example: 
+
+.. code-block:: typoscript
+       page.includeCSS {
+               inline = EXT:test/Resources/Public/Css/inline.css
+               inline {
+                       inline = 1
+                       forceOnTop = 1
+                       media = all
+               }
+               other = EXT:test/Resources/Public/Css/other.css
+       }
+
+
+Some notes on the implementation:
+
+External files are not inlined.
+The inline-css is compressed if config.compressCss is set.
+Most other properties (.allWrap, .disableCompression, .forceOnTop, .if, .media, .title) work even if '.inline' is set. 
+If '.import' and '.inline' are both set , the file is loaded via @import.
+
+.. index:: Frontend, TypoScript
index 5ca0187..e803a95 100644 (file)
@@ -303,8 +303,9 @@ class PageGenerator
                                 empty($cssFileConfig['disableCompression']),
                                 (bool)$cssFileConfig['forceOnTop'],
                                 $cssFileConfig['allWrap'],
-                                (bool)$cssFileConfig['excludeFromConcatenation'],
-                                $cssFileConfig['allWrap.']['splitChar']
+                                (bool)$cssFileConfig['excludeFromConcatenation'] || (bool)$cssFileConfig['inline'],
+                                $cssFileConfig['allWrap.']['splitChar'],
+                                $cssFileConfig['inline']
                             );
                             unset($cssFileConfig);
                         }
@@ -336,8 +337,9 @@ class PageGenerator
                                 empty($cssFileConfig['disableCompression']),
                                 (bool)$cssFileConfig['forceOnTop'],
                                 $cssFileConfig['allWrap'],
-                                (bool)$cssFileConfig['excludeFromConcatenation'],
-                                $cssFileConfig['allWrap.']['splitChar']
+                                (bool)$cssFileConfig['excludeFromConcatenation'] || (bool)$cssFileConfig['inline'],
+                                $cssFileConfig['allWrap.']['splitChar'],
+                                $cssFileConfig['inline']
                             );
                             unset($cssFileConfig);
                         }
index 46fc1c0..a17cf51 100644 (file)
@@ -4922,6 +4922,8 @@ Each file has optional properties:
 
 .excludeFromConcatenation - If config.concatenateCss is enabled, this prevents the file from being concatenated.
 
+.inline - Inline the contents of the CSS file using a <style> tag.
+
 Example:
 
 includeCSS {