Sieht der folgende Code für Dich ok aus? Zur Info habe noch einen 2. Viewhelper für inline was ich eigentlich nicht wollte aber trotzdem mal gemacht habe.
Fluid:
<f:asset.css identifier="bootstrap" href="{gf:scssfile(importpath:'EXT:gedankenfolger_sitepackage/Resources/Public/Scss/Bootstrap/',filename:'bootstrap.scss',targetfile:'EXT:gedankenfolger_sitepackage/Resources/Public/Css/bootstrap.css')}" />
PHP:
<?php
declare(strict_types=1);
namespace Gedankenfolger\GedankenfolgerSitepackage\ViewHelpers;
use ScssPhp\ScssPhp\Compiler;
use ScssPhp\ScssPhp\OutputStyle;
use ScssPhp\ScssPhp\Exception\SassException;
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
use TYPO3\CMS\Core\Utility\GeneralUtility;
final class ScssfileViewHelper extends AbstractViewHelper
{
protected $escapeOutput = false;
public function initializeArguments(): void
{
$this->registerArgument(
'importpath',
'string',
'The path to the folder containing the SCSS file',
true
);
$this->registerArgument(
'filename',
'string',
'The name of the SCSS file',
true
);
$this->registerArgument(
'outputStyle',
'string',
'The output style, e.g. "expanded" or "compressed"',
false,
'compressed'
);
$this->registerArgument(
'targetfile',
'string',
'The relative target path for the generated CSS file (e.g. "fileadmin/compiled/")',
false,
'fileadmin/compiled/'
);
}
public function render(): string
{
$importpath = $this->arguments['importpath'];
$filename = $this->arguments['filename'];
$outputStyle = $this->arguments['outputStyle'];
$targetfile = $this->arguments['targetfile'];
// Convert the relative folder path into an absolute path.
$absoluteImportPath = rtrim(GeneralUtility::getFileAbsFileName($importpath), '/\\');
$scssFile = $absoluteImportPath . '/' . $filename;
// Determine the target file path (absolute) and public URL.
$targetDir = GeneralUtility::getFileAbsFileName($targetfile);
// Ensure the target directory exists.
if (!is_dir($targetDir)) {
GeneralUtility::mkdir_deep($targetDir);
}
// Create a unique name based on the SCSS file and its modification time.
$cacheKey = md5($scssFile . filemtime($scssFile) . $outputStyle);
$cssFilename = pathinfo($filename, PATHINFO_FILENAME) . '_' . $cacheKey . '.css';
$cssFileAbsolute = rtrim($targetDir, '/\\') . '/' . $cssFilename;
// Check if the CSS file already exists (cache hit).
if (!file_exists($cssFileAbsolute)) {
try {
$compiler = new Compiler();
$compiler->setImportPaths($absoluteImportPath);
// Set the output style. Possible values: OutputStyle::EXPANDED or OutputStyle::COMPRESSED.
if (strtolower($outputStyle) === 'compressed') {
$compiler->setOutputStyle(OutputStyle::COMPRESSED);
} else {
$compiler->setOutputStyle(OutputStyle::EXPANDED);
}
// Dynamically build the SCSS code using the file name.
$scss = sprintf('@import "%s";', $filename);
$compiledCss = $compiler->compileString($scss)->getCss();
// Write the compiled CSS to a file.
file_put_contents($cssFileAbsolute, $compiledCss);
} catch (SassException $e) {
// Log the error for further debugging.
GeneralUtility::sysLog('SCSS compilation error: ' . $e->getMessage(), 'gedankenfolger_sitepackage', GeneralUtility::SYSLOG_SEVERITY_ERROR);
// Return a fallback value so that TYPO3 always receives a return value.
return '';
}
}
// Generate the public URL for the CSS file.
// It is assumed that $targetfile is reachable as a relative URL from the web root.
$cssFilePublicUrl = rtrim($targetfile, '/\\') . '/' . $cssFilename;
// Ensure the URL starts with a leading slash.
$cssFilePublicUrl = ltrim($cssFilePublicUrl, '/');
return $cssFilePublicUrl;
}
}