diff --git a/typo3/sysext/core/Classes/Page/PageRenderer.php b/typo3/sysext/core/Classes/Page/PageRenderer.php index 7b924305de38860d53aba7f7b9fcb6492771c468..ad556e19547b323e350885bf41bc3de64a7ff010 100644 --- a/typo3/sysext/core/Classes/Page/PageRenderer.php +++ b/typo3/sysext/core/Classes/Page/PageRenderer.php @@ -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 index 0000000000000000000000000000000000000000..036288a774d0429204bca2eaa07d35216f67f258 --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/master/Feature-81223-IncludeCSSinlineProperty.rst @@ -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 diff --git a/typo3/sysext/frontend/Classes/Page/PageGenerator.php b/typo3/sysext/frontend/Classes/Page/PageGenerator.php index 5ca01878dc9fe411d7ad27fafe4ede31d0403e54..e803a95d70c142b89727629ef509e70b97b9f8d9 100644 --- a/typo3/sysext/frontend/Classes/Page/PageGenerator.php +++ b/typo3/sysext/frontend/Classes/Page/PageGenerator.php @@ -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); } diff --git a/typo3/sysext/t3editor/Resources/Private/tsref.xml b/typo3/sysext/t3editor/Resources/Private/tsref.xml index 46fc1c0770a5cf7e7196ddc9b0812d7fde712c2c..a17cf510daaab2b571ba6a72ff2083210a750028 100644 --- a/typo3/sysext/t3editor/Resources/Private/tsref.xml +++ b/typo3/sysext/t3editor/Resources/Private/tsref.xml @@ -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 {